c#简要概括面向对象的三大特征(一)
本来计划用c#来详实地描述一下面向对象的上述三大特征,可是考虑到面向对象和c#语言的博大精深,这里只是简单地参考网上资源总结和归纳一下,没有什么新意,按照自己的理解加深一下对面向对象的认识。一家之言,不足或讹误之处望留意。
一、封装:c#类和结构
1、什么是封装
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装可以隐藏实现细节,使得代码模块化。
2、封装成类或结构
类和结构实际上是创建对象的模版,每个对象都包含数据,并提供了处理和访问数据的方法。
(1)、类定义了每个类对象(实例)可以包含什么数据和功能。举例来说,如果一个类表示客户,我们就可以定义字段customerId,name和address,以包含该客户的信息,还可以定义处理存储在这些字段中的数据的功能。接着,如我们常写的那样,new一下实例化对象,以表示某个客户,并为这个实例设置这些字段,使用其功能。
结构在内存中的存储方式(类是存储在堆(heap)上的引用类型,而结构是存储在堆栈(stack)上的值类型)、访问方式和一些特征(如结构不支持继承)与类不同。较小的数据类型使用结构可以提高性能。但在语法上,结构和类非常相似,主要的区别是使用关键字struct代替class来声明结构,在c#中,可以把结构看做是缩小的类。
(2)、类成员
类中的数据和函数称为类的成员。类成员可以分为数据成员和函数成员。
数据成员包含了类的数据——字段、常量和事件。
函数成员提供了操作类中数据的某些功能,包括方法,构造函数,属性和终结器(finalizer)、运算符和索引器。
(3)特殊的类
在封装类的时候,我们可能会按照实际的需要构造一些“特殊”的类(比如静态类,抽象类等),下面简要介绍说明一下常见的特殊的类。
<1>、静态类
如果类只包含静态的方法和属性,该类就可以是静态的。静态类在功能上与使用私有静态构造函数创建的类相同。不能创建静态类的事例。使用static关键字,编译器可以检查以后是否给该类添加了实例成员,如果是,就会产生一个编译错误。
<2>、密封类
c#允许把类和方法声明为sealed。对于类来说,这就表示不能继承该类;对于方法来说,这表示不能重写该方法。但是在方法上使用sealed是没有意义的,除非该方法本身是某个基类上另一个方法的重写形式。如果定义一个新方法,但不想让别人重写它,首先就不要把它声明为virtual。但如果要重写某个基类方法,sealed关键字就提供了一种方式,可以确保为方法提供的重写代码是最终的代码,其他人不能再重写它。
<3>、抽象类
c#允许把类和方法声明为abstract,抽象类不能被实例化,而抽象函数没有执行代码,必须在非抽象的派生类中重写。
{
public abstract void TestMethod(); //抽象函数没有执行代码
}
<4>、部分类
partial关键字允许把类,结构或接口放在多个文件中。一般情况下,一个类存储在单个文件中。但有时,多个开发人员需要访问一个类,或者某种类型的代码生成器生成了一个类的某部分,所以把类放在多个文件中是有益的。
<5>、Object类
众所周知,.net类都派生自System.Object。这个类的方法是所有.net类都实现的方法。
方法 访问修饰符 作用
string ToString() public virtual 返回对象的字符串表示
int GetHashCode() public virtual 在实现字典(散列表)时使用
bool Equals(object obj) public virtual 对对象的实例进行相等比较
bool Equals(object obja,object objb) public static 对对象的实例进行相等比较
bool ReferenceEquals(object obja,object objb) public static 比较两个引用是否指向同一个对象
Type GetType() public 返回对象类型的详细信息
object MemberwiseClone() protected(不能重写) 进行对象的浅表复制
void Finalize() protected virtual 析构函数的.net版本
(4)、结构(struct)
在许多方面,可以把c#中的结构看做是缩小的类。它基本上与类相同,但更适合于把一些数据组合起来的场合。下面介绍它与类的区别:
<1>、结构是值类型
结构是值类型,它存储在堆栈中或存储为内联(inline)(如果它是另一个对象的一部分,就会保存在堆中),其生存期的限制与简单的数据类型一样。
注意:因为结构是值类型,所以new运算符和类及其他引用类型的工作方式不同。new一个结构并不分配堆中的内存,而是调用相应的构造函数,根据传递给它的参数,初始化所有的字段。
结构遵循其他数据类型都遵循的规则:在使用前所有的元素都必须进行初始化。在结构上调用new运算符,后者给所有字段赋值,结构就可以完全初始化了。当然,如果结构定义为类的成员字段,在初始化包含对象时,该结构会自动初始化为0.
结构是值类型,所以会影响性能,但根据使用结构的方式,这种影响可能是正面的,也可能是负面的。正面的影响是为结构分配内存时,速度非常快,因为它们将内联或者保持在堆栈上。在结构超出了作用域被删除时,速度也很快。但是,另一方面,只要把结构作为参数来传递或把一个结构赋给另一个结构(比如customerA=customerB,customerA和customerB都是结构),结构的所有内容就被复制,而对于类,只是复制类的引用。这样,就产生了性能损失。根据结构的大小,性能损失也不同。
注意:结构主要用于小的数据结构。但是当把结构作为参数传递给方法时,就应把它作为ref参数传递,以避免性能损失——此时只传递了结构在内存中的地址,这样传递速度就与在类中的传递速度一样快了。但是必须要小心,因为通过ref方式,被调用的方法可以改变结构的值。
<2>、结构不能被继承
结构不是为继承设计的。不能从一个结构中继承,唯一的例外是结构派生于类System.Object.因此结构也可以访问System.Object的方法。结构的继承链是这样的:每个结构派生于System.ValueType,System.ValueType派生于System.Object。System.ValueType并没有给System.Object添加任何新成员,但提供了一些更适合结构的执行代码。
注意:结构可以实现接口。也就是说结构并不支持实现继承,但支持接口继承。
a、结构总是派生于System.ValueType,它们还可以派生于任意多个接口。
b、类可以派生于用户选择的另一个类,它们还可以派生于任意多个接口。
<3>、结构的构造函数(结构不能包含显式的无参构造函数)
为结构定义构造函数的方式与为类定义构造函数的方式相同,但不允许定义无参数的构造函数,其原因影藏在.net运行库的执行方式中。即:.net运行库不能调用用户提供的定制无参数构造函数,因此ms禁止在c#中的结构内使用无参数的构造函数。
作者:Jeff Wong
出处:http://jeffwongishandsome.cnblogs.com/
本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。