内容提要
本文你将学习到:
- 什么是对象(Object)
- 什么是类(Class)
- 如何定义一个类
- 类的成员(方法,属性,字段等)
概述
在此之前,我们学习的基本都是C#编程的最基础知识,如果把学习C#语言类比学习中文的话,目前这个阶段相当于我们刚学习完汉语拼音和汉字。那么如何将这些汉字结合起来组成句子,对应C#编程中如何使用这些C#基础知识来编写程序,就需要我们继续探索和学习熟练掌握C#语言更丰富的知识。
从本节起,我们将进入C#语言的面向对象编程(OOP:Object-Oriented Programming)部分的学习。面向对象编程也是C#编程的核心思想,熟悉并掌握C#的面向对象编程,才算真正打开C#程序设计的大门。
之前我们写示例代码的时候,所有的功能代码都被写在了Program.cs
这个文件中,这是一种面向过程的编程方式。
当程序功能较少的时候不会暴露什么问题,但当程序功能越来越多的时候,面向过程编程将是一个灾难,这种方式编写出来的代码极难阅读,极不方便维护和扩展,也没有模块化,代码的复用性不高。而面对对象编程正是为解决这些问题而设计的。
对象
现实世界中的实体统称为对象(世间万物皆对象),比如有生命的(人,动物)或者无生命的(车,房,电脑,智能手机,平板等等),具体的(书,电视)或者抽象的(税率,条例等)。
对象有两个特征:属性和行为。比如房子(House)可能有以下的属性:
- 门牌号(House Number)
- 业主(Owner)
- 房间数(Number of Rooms)
- 面积(Area)
- 室内温度(Temperature)
- 修建年份(Year)
- 购买价格(Buying Price)
有以下的行为(方法):
- 开门(Open Door)
- 关门(Close Door)
- 安装空调(Install Air Conditioner)
- 测量室内温度(Measure Indoor Temperature)
或者一只狗有这些属性:颜色,年龄,体重,类型等等,它有的行为:吠,吃,跑,嗅等。
在C#语言中,以上的房子或者狗的属性我们称之为字段或者属性(fields/properties),而行为被称之为方法(methods)。这些字段/属性/方法又统称类的成员。
在一个类中,字段/属性/方法这些类的成员都是可选的,也就是说一个类中可以没有字段、属性、方法,即一个空类。
那么如何将实现世界中的对象与C#程序语言结合起来呢,这里就该我们的”类”出场了。
示例演示为什么要使用类和对象
看来看一个不使用类和对象定义若干个房子的实例代码:
// House 1
string houseNumber1;
string houseOwner1;
float houseArea1;
// House 2
string houseNumber2;
string houseOwner2;
float houseArea2;
// House 3
string houseNumber3;
string houseOwner3;
float houseArea3;
以上示例代码中,基于之前学习过的变量的相关知识,我们使用不同的变量来描述不同房子的不同属性。
比如房子的房号,这里有3个房子,我们就需要分别定义3个不同的房号变量:house1HouseNumber
。类似的,我们还分别用不同变量来定义的房子的户主、面积属性。
想一想,如果再有几个房子,我们怎么来维护这些属性信息呢?
类
类是具有相似属性和方法的对象的集合(是用于创建相同类型的对象的模板)。
类的语法结构:
[access modifier] class className
{
//类的成员
[class body]
}
在C#语言中,还有与类相似声明的类型,如结构(struct)和记录(record)。其中结构是值类型的数据类型,记录是C# 9中引入的引用类型的数据类型,它是一种为处理数据模型提供特殊的语法和行为的类。在声明结构和记录时,请分别使用关键字
struct
和record
。关于结构和记录,将在专门的章节进行介绍。
还是拿Program.cs
这个文件来举例,对应类的书写语法:
class Program
{
static void Main(string[] arguments)
{
}
}
类的成员
成员分类:
- 字段
- 属性
- 方法
- 索引
- 委托
- 事件
- 嵌套类
以下是定义一个类的语法结构:
[access modifier] class className
{
#region 类的成员
// 成员-变量
[access specifier] <data type> variable1;
[access specifier] <data type> variable2;
...
[access specifier] <data type> variableN;
// 成员-属性
[access specifier] <data type> <property1> {get;set;}
[access specifier] <data type> <property2> {get;set;}
...
[access specifier] <data type> <propertyN> {get;set;}
// 成员-方法
[access specifier] <return type> method1(parameter_list) {
// 方法体
}
[access specifier] <return type> method2(parameter_list) {
// 方法体
}
...
[access specifier] <return type> methodN(parameter_list) {
// 方法体
}
#endregion
}
现在我们还是以上面的房子作为示例,来演示在C#语言编程中是如何用类描述现实生活中的实际对象的。
以上面提到的房子(House)属性和方法为例,新建一个House类:
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
}
}
class House
{
public string HouseNumber { get; set; }
public string Owner { get; set; }
public float Area { get; set; }
}
}
为了示例方便,直接将House
类与Program
类放在了同一个文件中。但在正式的项目开发中,建议用单独的类文件来存放专门的类。比如,这里我们可以单独创建一个名为House.cs
的文件,如下图:
新建类的具体步骤如下:
1.打开添加新项窗口
2.添加新项
类的使用(实例化对象)
上面我们创建了一个类(House
),那么,我们应该如何使用这个类呢?
与之前学习过的变量声明方式相同,我们只需在使用的地方声明一个类型为House
的变量即可,如下:
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
House house;
}
}
}
以上示例代码中声明了一个类型为House
的变量house
,但并未对其进行赋值,同时我们还未使用这个变量进行其他操作,所以,Visual Studio编译器被提示如下信息:
声明了变量”house”,但从未使用过
C#语言中被定义为类的类型是引用类型。要将类实例化成一个实例对象,需要使用关键字new
,一个只声明但未实例化的引用类型变量的默认值为null
。接下来,我们就用new
关键字来实例化一个House对象,示例代码如下:
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
House house;
house = new House();
}
}
}
语句house = new House();
即是实例化一个House对象。如果你觉得有些不好理解,那我们把House这个类比作设计师设计房子模型。new House()
就相当于建筑师按照设计模型用钢筋混凝土修了一个真正的房子,这就叫类的实例化。
在C#语言中,类的实例化得到的称之为对象。
House house; // house(我的房子) is null
// 使用new关键字实例化一个对象
// 创建对象时,在托管堆上为这个对象分配足够的内存空间,并将变量指向该对象在内存地址的引用。
// 好比:我是一名建筑设计师,手上有一张设计好的房子的设计图(House类),现在委托建筑师帮我修建(new House())。当建筑工程师按照设计把房子建好之后,告诉我这个房子的地址,我将房子的地址保存在一张小卡片(house)上。
// 这里的house对应小卡片,它是房子的引用地址(给房子做一个标签,标注这个房子是谁家的)
// 当我们需要用这个房子的时候,我根据这个标签就能找到。
house = new House();
现在,我们得到了一个房子(House)的实例,心急的你是否在想如何访问这个实例的属性,比如房号(HouseNumber
)呢?
C#语言中,访问对象的成员语法如下:
- 访问属性:
[变量名.属性名]
- 访问字段:
[变量名.字段名]
- 访问方法:
[变量名.方法名()]
如果你现在通实例house
来访问房号(HouseNumber
),控制台将不会有任何输出,如下:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
House house;
house = new House();
Console.WriteLine(house.HouseNumber);
Console.ReadKey();
}
}
}
因为我们还未设置house
对象的属性值。那么,我们就来看看实例对象是如何赋值的。对可以访问的对象属性也是使用等号(=)进行赋值的,示例代码如下:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
House house;
house = new House();
house.HouseNumber = "302";
house.Area = 120;
house.Owner = "张先生";
Console.WriteLine($"房号:{house.HouseNumber}");
Console.WriteLine($"户主:{house.Owner}
}
}
}
以上示例代码中,我们分别对房子的房号(HouseNumber)、面积(Area)、户主(Owner)进行了赋值,使用的语法是[变量名.属性名]=值
的方式。
类的成员的可访问性与定义时的访问修饰符有关,这里请我们全部设置成了
public
。关于访问修饰符将在后续章节作详细介绍,这里只作了解。
运行结果如下:
房号:302
户主:张先生
面积:120
回到本节最开始使用不同变量定义不同房子的场景:houseNumber1
,houseNumber2
,houseNumber3
,再对比类的特性,我们尝试用类来定义不同的房子,应该如何实现呢?
示例代码如下:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
House house1;
house1 = new House();
house1.HouseNumber = "302";
house1.Area = 120;
house1.Owner = "张先生";
House house2;
house2 = new House();
house2.HouseNumber = "503";
house2.Area = 90;
house2.Owner = "李先生";
House house3;
house3 = new House();
house3.HouseNumber = "606";
house3.Area = 150;
house3.Owner = "刘先生";
}
}
}
怎么样,使用类来管理和维护,代码看起来是否要整洁得多呢?
再结合我们之前已经学到的《C#隐式类型变量》以及C#的对象初始化器,可以将上面的代码简化成如下所示:
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var house1 = new House { HouseNumber = "302", Area = 120, Owner = "张先生" };
var house2 = new House { HouseNumber = "503", Area = 90, Owner = "李先生" };
var house3 = new House { HouseNumber = "606", Area = 150, Owner = "刘先生" };
}
}
}
发表评论
登录用户才能发表评论, 请 登 录 或者 注册
热门评论(1)
风古右 (2023-05-25)
大道至简,取其精华去其糟粕