在C#编程中常会用到静态方法、静态类、虚拟方法、抽象类、抽象方法,究竟这些方法有什么关系,有什么区别,有什么需要注意的,什么时间使用正确方法,下面我们通过一些小例子讲述这些小小的疑问。
1):静态
就从静态方法说起。要讲述静态方法,我发现又得从静态类说起。静态类是使用Static修饰符定义的Class,在C#中静态类只包含从 Object 继承的实例成员,没有可调用的构造函数,因为静态类不用构造函数实例化。使用static修饰符定义的变量称为静态变量。静态变量在被创建并加载后生效,当卸载后失效。静态变量的初始值为此类型变量的默认值。为了方便明确赋值检查,静态变量被认为是初始化过的。使用Static定义的方法称为静态方法,
1: class Person
2: {
3: public static int age;
4:
5: public string Name
6: {
7: get;
8: set;
9: }
10: }
11: //
12: class Test
13: {
14: public void MyMethod()
15: {
16: Person per = new Person();
17: per.Name = "李四";
18: Person.age = 19;
19: }
20: }
21: //测试Class,包含Main函数入口
22: class Program
23: {
24: static void Main(string[] args)
25: {
26: Person p = new Person();
27: p.Name = "张三";
28: Person.age = 18;
29: Test t = new Test();
30: t.MyMethod();
31: Console.WriteLine(p.Name);
32: Console.WriteLine(Person.age);
33: Console.ReadKey();
34: }
35: }
上面的定义只定义一个静态的变量age,在变量的定义之初就给变量赋值,并在加载程序后一直驻留内存不会销毁,生命周期直到程序结束。以下调用age这个参数,在测试函数中我们直接就可以类名.age调用这个变量,而其他不管是函数还是变量都需要New一个新的对象去调用。
如果上面的定义Class也是静态的,注意不能在静态类中声明实例成员,也就说静态类中的成员必须也是静态的,如果没有定义静态的,使用这些实例成员必须New一个对象,而静态是不能New一个对象的,就失去意义了,另外静态类中的成员一般不参与外界交互,只是内部方法是用。
1: static class Person
2: {
3: public static int age;
4: public static string Name { get; set; }
5: }
6: //
7: class Test
8: {
9: public void MyMethod()
10: {
11: Person.age = 19;
12: }
13: }
14: //测试Class,包含Main函数入口
15: class Program
16: {
17: static void Main(string[] args)
18: {
19: Person.age = 18;
20: Test t = new Test();
21: t.MyMethod();
22: Console.WriteLine(Person.age);
23: Console.ReadKey();
24: }
25: }
这个类定义为静态的,使所有的成员也定义为静态的,在程序的运行中任何地方都能访问的到,静态成员、静态类只有在程序退出的时候才会释放资源。
静态类的注意事项:
•静态类不能被其他类继承
•静态类只能继承自Object类。(静态类不能继承自其它类。)
•继承(多态)、静态本身就是相反的。
•静态类不能实现任何接口,(因为接口中的成员都是实例成员。*)
一一解释之:
1.静态类不能被继承,是因为静态类相当于Abstract+sealed抽象加密封,继承没有意义。
2.静态类只能继承自Object类。C#中所有的类都看做是对象,都继承Object
3.继承就是为了实现实例化,而静态则刚好相反,在静态的保存上并非是同在一样内存区,声明静态时会有专门的静态存储区域存储这么函数,变量,类型。
4.接口是为了定义实例成员,而静态不是实例成员,所以静态也不实现任何接口。
2):抽象
抽象的类一般在接口,继承中使用,主要用于多态的使用。MSDN上这样定义抽象类:抽象类是一些留有部分或全部成员未实现的类,以便可以由派生类来提供实现。 抽象类的生命使用关键字:abstract 。在类声明中使用 abstract 修饰符以指示某个类只能是其他类的基类。 标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现。抽象的成员必须写在抽象类中,不允许私有,因为需要子类的访问。
1: //声明一个抽象类,抽象类中一个抽象的方法
2: public abstract Class
3: {
4: public abstract void Eat();
5: }
子类在使用抽象类时间,想使用一个接口规则似的,必须实现其抽象方法,Override覆盖其抽象方法.
抽象类,抽象成员的注意事项:
•抽象类中的抽象成员不能使用private访问修饰符,可以使用其他访问修饰符。
•父类中不能有任何实现。
•子类中必须重写(除非:子类也是一个抽象类。)
•抽象方法必须在抽象类中。
一一解释之:
1.既然抽象,就是用其他的覆盖或者部分实现,后来实现,如果Private不公开就没什么意义了
2.抽象的父类不实现
3.父类中出现的抽象方法子类必须实现,否则编译错误,就好像一个接口一样使用,抽象就是定义一个规则
4.抽象的方法必须写在抽象的类中,只是语法规则,为什么会这样呢? 语法规则,遵守规则吧,以后再讨论为什么这样设计。
3):虚拟
virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。 例如,此方法可被任何继承它的类重写。
1: public virtual double Area()
2: {
3: return x * y;
4: }
调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。 也就是做,虚拟的方法可以不重写这个方法。重写防范也是Override覆盖。
默认情况下,方法是非虚拟的。不能重写非虚方法。
virtual 修饰符不能与 static、 abstract, private 或 override 修饰符一起使用。
在静态属性上使用 virtual 修饰符是错误的。 通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。
虚拟方法成员的注意事项:
•父类中必须有实现。
•子类中可以不重写。
•虚方法可以在普通类中。(有序方法的类是可以(可能)被实例化的。)
一一解释之:
1.必须实现是说必须有实现,哪怕是空的大括号{}
2.子类可以不重写,有需求才重写。
3.任何普通类中都可以。
这里只是简单的概念的理解,如果实践的理解还要充分认识多态的使用,在多态中将这么概念的只是不断重复使用,达到优秀程序架构设计的作用。如果想更深入的了解,还需要在以后的日子里关注面向对象的编程,关注后来日子的日志随笔更新!