【转】C#类的分类(静态类、实例类、嵌套类、结构、简单的抽象类、简单的密封类)
静态类 -------------------------------------------------------------------------------- 静态类就是在class关键字前加入了static关键字,基本语法是static Class ClassName{} 。 静态类有几个特点: 1.静态类只能包括静态成员 2.类本身无法被实例化,也就是不能创建静态类的对象 3.静态类无法被继承 4.无法包含实例构造方法 所以我们在创建静态类的时候,必须注意到以上四点,下面的实例是简单的静态类的使用。 静态类实例 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //静态类不能被实例化,因为静态类中的成员都是静态的,调用静态类中的成员使用类名引用。 6 Console .WriteLine ( StaticClass.a); 7 } 8 } 9 //定义一个静态类名字叫做StaticClass 10 static class StaticClass 11 { 12 //定义一个静态成员 13 public static int a=2; 14 } 结果就是2. 静态类所提供的数据成员和方法成员具有唯一性,就如同使用了全局变量,所以比较适合封装公用的成员。 结构 -------------------------------------------------------------------------------- 在c#中也有结构,结果就是几个数据组成的数据结构,通常用来封装小型相关变量组,结构也可以看成是种轻量级的类,它的行为与类相似,但是不支持复杂的类功能,例如:继承。在结构中也可以创建各种成员,比如:构造方法、常数、字段、方法、属性、索引器、运算符、事件、嵌套类型等,但是如果往一个结构中放入比较复杂的成员,对与结构来说就和类没有区别了,也就是失去了结构的特点,这时应该用创建类来代替创建结构。结构的基本语法是 public struct StructName{} 。 结构在MSDN上的概述: 结构是值类型,而类是引用类型。 与类不同,结构的实例化可以不使用 new 运算符。 结构可以声明构造函数,但它们必须带参数。 一个结构不能从另一个结构或类继承,而且不能作为一个类的基。所有结构都直接继承自 System.ValueType,后者继承自 System.Object。 结构可以实现接口。 结构的副本由编译器自动创建和销毁,因此不需要使用默认构造函数和析构函数。 在结构声明中,除非字段被声明为 const 或 static,否则无法初始化。 创建结构对象的时候不需要使用new关键字,由于直接存储对象数据、省略了对象引用的步骤,同时也就提升了使用性能,这就是使用结构的好处。结构同样具有自己专门的默认构造方法,它会自动引用,当然我们也可以创建自定义的构造方法,而此时就需要使用new关键字,引用这个构造方法了。看下面的代码: 结构体实例 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //创建结构对象,不必使用new关键字 6 StructName structobj; 7 structobj.kuan = 3; 8 structobj.chang = 5; 9 Console .WriteLine ("面积是"+ structobj.Getmj()); 10 11 //使用结构体的构造方法,必须使用和类创建对象的方法相同new 12 StructName structobj1 = new StructName(4,6); 13 } 14 } 15 //定义一个静态类名字叫做StructName 16 public struct StructName 17 { 18 public int chang; 19 public int kuan; 20 public int Getmj() 21 { 22 return chang * kuan; 23 } 24 25 //结构体的构造函数 26 public StructName(int chang1, int kuan1) 27 { 28 chang = chang1; 29 kuan = kuan1; 30 Console.WriteLine("使用构造方法的面积是" + chang1 *kuan1); 31 } 32 } 结果: 面积是15 使用构造方法的面积是24。 因为结构声明时无法初始化,所以在使用new创建结构对象时,必须在定义结构的有参构造方法,给结构中的已定义的无初值的变量赋一个值,否则就会报错,如程序的第28、29行。大家可以试一试如果是在类的有参构造方法中,即使没有28、29行,也能正常的编译出结果。 嵌套类 -------------------------------------------------------------------------------- 在类一系列中,我也提到过类成员中还包括一中嵌套类,其实嵌套类就是类中的一个类,由于嵌套类在类的内部,属于外部类的内部成员,所以外部类的private访问权限对内部类是无效的,也就是说,内部类可以使用外部类的任何成员,创建嵌套类insideClassName的基本语法如下: Class outclassName { public class insideclassName { } } 当外部程序代码要访问嵌套类的时候,必须引用外层类的名称像引出外部类的其他静态成员一样使用类名加运算符“.”的方式,创建嵌套类的对象具体语法如下: outclassName.insideclassName bj=new outclassName.insideclassName(); 如果再用嵌套类的对象时,再使用obj.的方式引用出,我们来看下面的例子: 嵌套类实例 1namespace hello 2{ 3 class program 4 { 5 static void Main(string[] args) 6 { 7 //创建内部类的实例,必须把内部类作为静态成员,使用外部类名来引用 8 //而使用外部类的实例成员,必须使用外部类的对象来引用 9 outclassName.insideclassName i = new outclassName.insideclassName(); 10 11 //用内部类的对象引用出内部类的实例成员(方法say()) 12 i.say(); 13 } 14 } 15 //定义一个外部类 16 class outclassName 17 { 18 //定义一个外部类的变量s,它的访问权限是私有的。 19 string s = "我是外部类的变量s"; 20 //定义一个内部类,因为它是外部类中的一个类成员,在第三方类(Program)中, 21 //要想调用这个类中,就必须加上public,和其他外部类的公用方法一样。 22 public class insideclassName 23 { 24 //创建一个外部类的对象o,用于便于内部类访问外部类成员。 25 outclassName o = new outclassName(); 26 //定义一个内部类的方法say 27 public void say() 28 { 29 //调用外部类中的字段s,使用外部类的对象o来引用,而且s的访问权限不必是public。 30 Console.WriteLine("用内部的方法调出外部的变量"+o.s); 31 } 32 } 33 } 34 35} 结果就是: 用内部的方法调出外部的变量我是外部类的变量s 请按任意键继续. . . 使用嵌套类注意:嵌套类要想被其他类访问到,必须像外部类的一个公用成员一样,要加public修饰符;创建嵌套类的对象时,要用外部类的类名来调用,这有点像把内部的嵌套类作为外部类的一个静态成员来使用;嵌套类要想使用外部类的成员,也是需要创建用外部类名(.静态成员)或是外部类的对象(.实例成员)来调用,唯一与两个并列类访问不同的是,嵌套类可以调用外部类的私有成员(private修饰),而并列类只能用公有成员(public修饰)。 下面我们要来学习最后两个类,这两个类我在标题的时候注明了是简单的抽象类和简单的密封类,原因就是这两个类都是面向对象语言相对面向过程的一大进步,他们利用了面向对象的继承性,要想学懂这两个类必须在学到继承后,再相信的讲解,这里我只是把他们的大体定义和基本结构写明,具体的应用我会在学习继承的时候,着重讲解。 抽象类 -------------------------------------------------------------------------------- 在实际项目中,我们定义一个抽象类主要是为派生类提供可共享的基类的公共定义,抽象类中可以包括抽象方法,抽象方法就是没有方法体,只有方法的定义,抽象方法具体由继承这个包含抽象方法的抽象类的子类中的方法来实现。是不是很难理解呢?没关系!同学们,现在我们只需要记住因为一个类中有了没有实现的抽象方法,所以把这个类也定义为抽象类,也就是说,抽象方法一定在抽象类中,但是抽象类中可以没有抽象方法,抽象类的和抽象方法都需要加入关键字abstract,下面我们来一定一个抽象类,并且这个抽象类中包括一个抽象方法,大家先记住他们的基本语法,日后我会详细讲解。 抽象方法的基本语法 1 //定义一个抽象类abstractclassName 2 abstract class abstractclassName 3 { 4 //定义一个抽象方法abstractMethods 5 abstract public void abstractMethods(); 6 } 7 使用抽象类还要记住二点,一:因为抽象类中有可能存在抽象方法,也就是存在没有实现的方法,所以抽象类无法被实例化,也就是无法创建类的实例对象;二:定义抽象方法的时候,为了让继承的子类能够实现这个抽象方法,也就必须把抽象的方法定义成公有成员,这样在抽象类的外部才能访问到这个抽象方法。 密封类 -------------------------------------------------------------------------------- 密封类的定义是通过sealed关键字来实现的,密封类可以用来限制扩展性,我也听过把密封类叫成太监类的说法,很形象的说明了密封类的特点,就是没有子类,也就是密封类无法被继承,这一点和静态类一样,下面来看看密封类的基本语法: sealed class sealedclassName { 类的主体; } 密封类除了不能被继承,其他的用法和实例类基本一致,可以有多个构造方法,可以有静态的、也可以有实例的,类的成员也是可以有静态的和实例的。所以就不再演示密封类的用法了,对于密封类来说,它与面向对象编程技术的灵活性和扩展性是相抵触的,所以通常情况下,不建议定义密码类。 静态类、实例类、嵌套类、结构、简单的抽象类、简单的密封类 确实比较有趣。。这里 1.静态类,2.结构,3.密封类 这三者,都是 挥刀自宫,没有 OO特性的。——要了解OO特性,其实很简单,只需要打开设计模式的 PPT,看看那些类图。。设计模式中大量使用到了 OO特性。。反过来说,设计模式类图中用不到的 这些 构造块,其实,很可能就是没有 OO特性的。。 1.静态类:与静态有关的任何构造块,全部没有 OO特性。所谓静态,即为全局,之所以要全局,就是为了‘稳定’——而 OO特性,天生是为了 OCP 为了可扩展,面对变化——所以,静态static关键字 出现的地方,就失去OO特性。 单例模式中的static,其实只是为了让 类的使用者至少能有办法拿到该类的实例,并不是体现 OO特性。 2.结构:这确实是一个非常有意思的东西。因为在C++中,大量使用结构,而Java中完全摒弃 结构 。首先,结构是 值类型。C++中,绝大部分的类型都是 值类型。如果要让值类型获得 引用类型 的特征,需要‘取地址’操作,得到的地址之后操作地址,才有了面向对象的意义——GOF23种设计模式,首先是针对C++编写的,个人观点,对于老前辈,还是要给于一定的尊重。 反过来,Java作为对C++某种程度上的颠覆,除了8种基本类型(不是对象)外,所有的自定义类型都是 引用类型。Java,10几年来,变化确实比较小,这也是它最近被诟病不能与时俱进的一大杯具。但,把OO精神推向纵深的貌似要属它。因为学习曲线低,很容易入门。除了8种基本类型(这些类型不用学,基本上所有语言都用),只要你自定义了类型,它天生就是 引用类型。 再看看C#。。这位老兄的优势是,背靠大山,得天独厚。它既保留了C++复杂语法中,关于值类型(可以自定义的值类型,就是 Struct——ValueType。。枚举类型其实也是一种结构)的部分,又大量借鉴了Java的引用类型。如果使用C#,又需要写出 OO风格 的代码,当然,最好多使用 Class,而不是 Struct。Struct的用武之地,在于封装那些不太赋予变化的值,像枚举这样的封装,也有很大用处。 3.密封类。这个构造大概基本上会在 框架 中用到较多。我们自己写的类,如果不想被别人继承,那就把类标记成 Internal,别人也就看不到你这个类了。——当然,如果别人能拿到源码,或者反编译得到,那就是两码事了。。那你用sealed关键字,岂非也是不保险的。。人家可以改嘛。
生命不息,奋斗不止