本节课我们来学习类的扩展分类,看我的标题中就罗列出了类的分类,类按照声明方式和功能定义共分为这六种类,
实例类就是我们一直在用的类,class关键字前没有其他的修饰符,之前已经有很多实例类的使用方法了,我们今天主要是学习其他五种类。
静态类
静态类就是在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 {
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 }
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。
使用构造方法的面积是24。
因为结构声明时无法初始化,所以在使用new创建结构对象时,必须在定义结构的有参构造方法,给结构中的已定义的无初值的变量赋一个值,否则就会报错,如程序的第28、29行。大家可以试一试如果是在类的有参构造方法中,即使没有28、29行,也能正常的编译出结果。
嵌套类
在类一系列中,我也提到过类成员中还包括一中嵌套类,其实嵌套类就是类中的一个类,由于嵌套类在类的内部,属于外部类的内部成员,所以外部类的private访问权限对内部类是无效的,也就是说,内部类可以使用外部类的任何成员,创建嵌套类insideClassName的基本语法如下:
Class outclassName
{
public class
insideclassName
{
}
}
当外部程序代码要访问嵌套类的时候,必须引用外层类的名称像引出外部类的其他静态成员一样使用类名加运算符“.”的方式,创建嵌套类的对象具体语法如下:
outclassName.insideclassName obj=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}
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,下面我们来一定一个抽象类,并且这个抽象类中包括一个抽象方法,大家先记住他们的基本语法,日后我会详细讲解。
抽象方法的基本语法
使用抽象类还要记住二点,一:因为抽象类中有可能存在抽象成员,也就是存在没有实现的成员,所以抽象类无法被实例化,也就是无法创建类的实例对象;二:定义抽象成员的时候,为了让继承的子类能够实现这个抽象方法,也就必须把抽象的成员定义成公有、或受保护的成员,这样在抽象类的外部才能访问到这个抽象成员。
密封类
密封类的定义是通过sealed关键字来实现的,密封类可以用来限制扩展性,我也听过把密封类叫成太监类的说法,很形象的说明了密封类的特点,就是没有子类,也就是密封类无法被继承,这一点和静态类一样,下面来看看密封类的基本语法:
sealed class sealedclassName
{
{
类的主体;
}
}
密封类除了不能被继承,其他的用法和实例类基本一致,可以有多个构造方法,可以有静态的、也可以有实例的,类的成员也是可以有静态的和实例的。所以就不再演示密封类的用法了,对于密封类来说,它与面向对象编程技术的灵活性和扩展性是相抵触的,所以通常情况下,不建议定义密码类。
本节课就讲到这里,下一节我们要来学习类六:索引器
本文转自叶子文文博客51CTO博客,原文链接http://blog.51cto.com/leafwf/185720如需转载请自行联系原作者
叶子文文