类的定义
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
类、命名空间的定义与使用
1.类
1.1类的声明及其修饰符
类(class)是最基础的C#类型。
类是一个数据结构,将状态(字段)和操作(方法和其他函数成员)组合在一个单元中。
class Car//定义Car类class是保留字,表示定义一个类,Car 是类名 {
public string model;
public void Run()
{
Console.WriteLine("{0}跑起来!!", model);
}
}
类的声明格式如下:
类修饰符class 类名
{
类体
}
其中,关键字class、类名和类体是必须的,其它项是可选项。
类修饰符包括new、public、protected、internal、private、abstract 和sealed。
类体用于定义类的成员。
下面介绍几个常用的类的修饰符。
(1)new:仅允许在嵌套类声明时使用,表明类中隐藏了由基类中继承而来的、与基类中同名的成员。
(2)public:表示不限制对该类的访问。
(3)protected:表示只能从其所在类和所在类的子类进行访问。
(4)internal:只有其所在类才能访问。
(5)private:只有.NET中的应用程序或库才能访问。
(6)abstract:抽象类,不允许建立类的实例。
(7)sealed:密封类,不允许被继承。
类的成员可以分为两大类:类本身所声明的以及从基类中继承来的。
类的成员包括以下类型:
字段:即类中的变量或常量,包括静态字段、实例字段、常量和只读字段。
方法:包括静态方法和实例方法。
属性:按属性指定的get方法和Set方法对字段进行读写。
属性本质上是方法。
事件:代表事件本身,同时联系事件和事件处理函数。
索引指示器:允许象使用数组那样访问类中的数据成员。
操作符重载:采用重载操作符的方法定义类中特有的操作。
构造函数和析构函数。
1.2 对象
对象是类的实例,是OOP应用程序的一个组成部件。
这个组成部件封装了部分应用程序,这部分应用程序可以是一个过程、一些数据
或一些更抽象的实体。
对象包含变量成员和函数类型。
它所包含的变量组成了存储在对象中的数据,其中包含的方法可以具有访问对象的功能。
复杂的对象可以不包含任何数据,只包含方法,表示一个过程。
在C#中和.NET Framework中的所有类型都是对象。
变量类型是一个类,变量也是一个对象。
下面的代码实现了访问Car类的对象和对象数据状态:
public class Car
{
public int number;
public string color;
private string _brand;
public Car()
{
}
public string brand
{
get
{
return _brand;
}
set
{
_brand = value;
}
}
}
下面代码在一个方法中实例化类对象并设置和访问数据状态:private void button2_Click(object sender, EventArgs e)
{
string pa;
Car c = new Car();
c.brand = "奔驰";
c.color = "黑色";
pa = c.brand;
}
1.3 字段、属性、方法
类的字段准确地说应该是类的数据成员,其定义是:用于存储类和类的实例相关数据的变量。
方法就是类的函数成员,是一个为实现类的某一个特定功能的函数。
因此也称为类的方法。
属性是一个代表类的实例或类中的一个数据项的函数成员。
从定义可以看出,属性是类的一个函数成员或者说是方法。
对类的属性的设定和获取可以用两个访问器set和get来实现。
字段,方法和属性的定义的区别如下示例:
class MyClass //定义类MyClass
{
//数据成员或者字段的定义
public int aa= 10;
private int bb;
//属性的定义
public int MyValue
{
set //设定属性
{
bb= value;
}
get //从属性获取值
{
return bb;
}
}
//方法的定义
public void SetValue()
{
}
}
从概念上可以区分字段和属性的区别,字段是一个用于存储数据的变量,属性是一个方法或者说是一个函数成员。
1.4 构造函数和析构函数
构造函数和析构函数是类中比较特殊的两种成员函数,主要用来对对象进行初始化和回收对象资源。
一般来说,对象的生命周期是从构造函数开始,以析构函数结束。
如果一个类含有构造函数,在实例化该类的对象时就会调用构造函数;如果含有析构函数则会在销毁对
象时调用它。
构造函数的名字和类名相同。
析构函数和构造函数的名字相同,但析构函数要在名字前加一个波浪号(~)。
当推出含有该对象的成员时,析构函数将自动释放这个对象所占用的内存空间。
每个类都有构造函数,在访问一个类的方法、属性或任何其他东西之前,首先执行的语句应是与类相应的构造函数。
即使没有声明它,编译器也会自动构造一系列的构造函数。
构造函数不声明返回类型,而且一般都是public类型,如果是private表明该类不能被实例化,这通常只用于静态成员的类。
析构函数是以类名加“~”来命名的。
.NET系统有垃圾回收功能,当某个类的实例被认为不再有效,并符合析构条件时,.NET的垃圾回收功能就会调用该类的析构函数。
下面的代码实现了Car类析构函数的声明:
public class Car
{
public int number;
public string color;
private string _brand;
public Car()//构造函数
{
}
public~Car()//析构函数
{
}
public string brand
{
get
{
return _brand;
}
set
{
_brand = value;
}
}
}
1.5 方法
1.5.1 方法的格式
定义方法的基本格式如下:
方法的访问属性返回类型方法名(参数列表)
{
方法的具体实现;
}
类中的功能大多数放在方法中实现。
下面的代码实现了
UpdateDatabase方法的定义:
public void UpdateDatabase(DataSet ds)
{
//具体实现代码;
}
1.5.2 方法的返回值
方法可以向调用方返回值。
如果返回类型(方法名称前列出的类型)不是void,则方法可以使用return关键字来返回值。
如果语句中return关键字的后面是与返回类型匹配的值,则该语句将该值返回给方法调用方。
return关键字还可以停止方法的执行。
如果返回类型为void,则可使用没有值的return语句来停止方法的执行。
如果没有return关键字,方法执行到代码块末尾时即会停止。
具有非void返回类型的方法才能使用return关键字返回值。
例如,
下面的两个方法使用return关键字来返回整数,代码如下:public class V oidTest
{
public int SquareNum(int num)
{
return num * num;
}
}
1.5.3 方法的参数
如果方法要更改数值,有时需要传递值给方法并从方法获得返回值。
下面是传递参数时的4种情况。
(1)值参数:声明时不带修饰符的参数是值参数,一个值参数相当于一个局部变量,初始值来自该方法调用时提供的相应参数。
在方法内对值参数的操作不会改变传给方法时变量的值,因为将值类型传递给方法时,传递的是副本而不是对象本身。
由于它们是副本,因此对参数所做的任何更改都不会在调用方法内部反映出来。
之所以叫做值类型,是因为传递的是对象的副本而不是对象本身,传递的是值,而不是同一个对象。
(2)引用参数:如果要传递原值并修改它,使用引用参数就非常方便。
因为引用参数传递了一个变量给方法而不仅仅传递它的值,所以对参数的操作会影响原值。
在传递时变量必须被初始化。
(3)输出参数:在传递参数前加out关键字即可将该传递参数设作一个输出参数。
输出参数用来返回一个结果。
它和引用参数的区别
是不必先初始化变量。
例如:
static void Method(out int i)
(4)参数数组:参数数组必须用params修饰词明确指定。
在方法的参数列表中只允许出现一个参数数组,而且在方法同时具有固定参数和参数数组的情况下,参数数组必须放在整个参数列表的最后,并且参数数组只允许是一维数组。
1.5.4方法的重载
方法重载是指调用同一方法名,但使用不同数据类型的参数或不同的次序。
只要类中有两个以上的同名方法,且使用的参数类型或者个数不同,编译器就可以判断在哪种情况下调用哪种方法。
下面的代码实现了MethodTest方法的重载:
public int MethodTest(int i, int j)
{
}
public int MethodTest(int i)
{
}
public string MethodTest(string s)
{
}
1.5.5封装、继承和多态
封装
在C#中可使用类来达到数据封装的效果,这样就可以使数据与方
法封装成单一元素,以便于通过方法存取数据。
除此之外,还可以控制数据的存取方式。
面向对象程序设计中一般以类作为数据封装的基本单位。
类将数据和操作数据的方法结合成一个单位。
在设计类时,不希望直接存取类中的数据,而是希望通过方法来存取数据。
如此就可以达到封装数据的目的,方便以后维护、升级,也可以在操作数据时多一层判断,提高安全性。
封装还可以解决数据存取权限问题,使用封装可以将数据隐藏起来,形成一个封闭的空间,用户可以设置哪些数据只能在这个空间中使用,哪些数据可以在空间外部使用。
如果一个类中包含敏感数据,则有些用户可以访问,有些用户却不能访问。
如果不对这些数据的访问加以限制,那么后果是很严重的。
所以,在编写程序时,要对类的成员使用不同的访问修饰符,从而定义它们的访问级别。
继承
继承是OOP最重要的特性之一。
任何类都可以从另外一个类继承,即这个类拥有它所继承类的所有成员。
在OOP中,被继承的类称为父类或基类。
C#提供了类的继承机制,但C#只支持单继承,不支持多重继承,即在C#中一次只允许继承一个类,不能同时继承多个类。
利用继承机制,用户可以通过增加、修改或替换类中方法对这个类进行扩充,以适应不同的应用要求。
利用继承,程序开发人员可以
在已有类的基础上构造新类。
继承使得类支持分类的概念。
在日常生活中很多东西比较有条理,那是因为它们有着很好的层次分类。
如果不用层次分类,则要对每个对象定义其所有的性质。
使用继承后,每个对象就可以只定义自己的特殊性质。
每一层的对象只需定义本身的性质,其他性质可以从上一层继承下来。
在C#中,接口允许多继承,可以通过继承多个接口来实现类似于C++中的多重继承。
在继承一个基类时,成员的可访问性是一个重要的问题。
子类不能访问基类的私有成员,但是可以访问其公共成员。
子类和外部代码都可以访问公共成员。
这就是说,只使用这两个可访问性,就可以让一个成员被基类和子类访问,同时也可以被外部的代码访问。
为了解决这个问题,C#还提供了第3种可访问性:protected。
只有派生类才能访问protected成员,基类和外部代码都不能访问protected 成员。
除了成员的保护级别外,用户还可以为成员定义其继承行为。
基类的成员可以是虚拟的,成员可以由继承它的类重写。
子类可以提供成员的其他执行代码。
这种执行代码不会删除原来的代码,仍可以在类中访问原来的代码,但外部代码不能访问它们。
如果没有提供其他执行方式,外部代码就访问基类中成员的执行代码。
虚拟成员不能是私有成员,因为成员不能同时由子类重写,也不能访问它。
基类还可以定义为抽象类。
抽象类不能直接实例化,要使用抽象类就必须继承这个类,然后再实例化。
多态
继承使得派生与基类的类在方法上有一定的重叠,因此可以使用相同的语法处理从同一个基类实例化的对象。
多态使得子类的实例可以直接赋予基类的变量,不需要进行强制类型转换,直接就可以通过这个变量调用基类的方法。
在派生于同一个类的不同对象上执行任务时,多态是一种极为有效的技巧,使用的代码最少。
可以把一组对象放到一个数组中,然后调用它们的方法,这些对象不必是相同类型的对象,在这种情况下多态的作用就体现出来了。
当然如果它们都继承自某个类,可以把这些派生类都放到一个数组中。
如果这些对象都有同名方法,可以调用每个对象的同名方法。
2.命名空间
命名空间是函数、类或组件的容器,把它们按类别放入不同的名字空间中,命名空间提供了一个逻辑上的层次结构体系,使应用程序能方便的找到所需代码。
1.命名空间的声明
用关键字namespace声明一个命名空间,命名空间的声明要么是源文件using语句后的第一条语句,要么作为成员出现在其它命名空间的声明之中,也就是说,在一个命名空间内部还可以定义名字空间
成员.
using System; //导入使空间
namespace类
{
class Car
{
public string model;
public string color;
}
}。