武侠世界中的:虚拟方法、重写方法、抽象方法
2007-02-10 22:40
295 查看
虚拟方法virtual
被修饰为虚拟的方法,实现是可变的,派生类可以重写基类的虚拟方法,也可以不重写基类的虚拟方法
1
public class Space
2
{
3
4
public static void Main(string[] args)
5
{
6
7
new Order().Submit();//to default department
8
new ShipOrder().Submit();//to default Ship department
9
new InOrder().Submit();//to default department
10
new OutOrder().Submit();//to default Out department /n to default department
11
}
12
}
13
14
15
public class Order
16
{
17
18
public virtual void Submit()
19
{
20
System.Console.WriteLine("to default department");
21
}
22
}
23
24
public class ShipOrder : Order
25
{
26
public override void Submit()
27
{
28
System.Console.WriteLine("to default Ship department");
29
}
30
}
31
32
public class InOrder : Order
33
{
34
35
}
36
37
public class OutOrder : Order
38
{
39
public override void Submit()
40
{
41
System.Console.WriteLine("to default Out department");
42
base.Submit();
43
}
44
}
在以上代码中,基类Order的Submit方法被修饰为virtual的,所以ShipOrder 和OutOrder 可以重新定义Submit的具体实现(用override 关键
字),并且还可以使用关键字base来调用基类的方法。
在讲到方法重写的时候,就必须要了解对象的数据类型转换。
在数据类型中,我们知道 数据容量小的(比如int)可以被安全的转换到数据容量大的(比如long)类型,反之是不安全的。
在对象世界正好相反,数据容量大的(子类)可以被安全的转换到数据容量小的(子类的基类)类型,反之是不安全的。
所以,所有的数据类型,都可以被安全的转为object,就是这个道理。
以下代码演示了对象的数据类型转换
1
Order order = new ShipOrder();//可以,子类转为基类
2
order.Submit();//to default Ship department
3
System.Console.WriteLine("type is {0}", order.GetType());//type is ShipOrder
4
ShipOrder ship = (ShipOrder)order;//可以,order是从ShipOrder转来的,但由于是基类转子类,必须强制类型转换
5
order.Submit();//to default Ship department
6
System.Console.WriteLine("type is {0}", ship.GetType());//type is ShipOrder
7
order = new Order();
8
ship = (ShipOrder)order;//不可以,order中没有ShipOrder的成员,编译正确,运行错误
9
InOrder inorder = new InOrder();
10
ship = (ShipOrder)inorder;//不可以,编译错误
在金庸小说《倚天屠龙记》中描述了virtual方法的含义
只听张三丰问道:“孩儿,你看清楚了没有?”张无忌道:“看清楚了。”张三丰道:“都记得了没有?”张无忌道:“已忘记了一小半。”
张三丰道:“好,那也难为了你。你自己去想想罢。”张无忌低头默想。过了一会,张三丰问道:“现下怎样了?”张无忌道:“已忘记了一
大半。”张三丰画剑成圈,问道:“孩儿,怎样啦?”张无忌道:“还有三招没忘记。”张三丰点点头,放剑归座。张无忌在殿上缓缓踱了一
个圈子,沉思半晌,又缓缓踱了半个圈子,抬起头来,满脸喜色,叫道:“这我可全忘了,忘得乾乾净净的了。”张三丰道:“不坏,不坏!
忘得真快”
1
public class Shadowboxing
2
{
3
public virtual void 白鹤亮翅()
4
{
5
}
6
public virtual void 如封似闭()
7
{
8
}
9
public virtual void 野马分鬃()
10
{
11
}
12
}
13
14
public class Zhang : Shadowboxing//张无忌继承张三丰的拳法
15
{
16
public override void 白鹤亮翅()
17
{
18
19
}
20
21
public override void 如封似闭()
22
{
23
24
}
25
26
}
我们再来看抽象方法abstract
抽象的方法隐含的为虚拟的方法,抽象的方法要求派生类必须重写,抽象的方法没有方法体。
1
public abstract class Order
2
{
3
4
public abstract void Submit();
5
}
6
7
public class ShipOrder : Order
8
{
9
public override void Submit()
10
{
11
System.Console.WriteLine("to default Ship department");
12
}
13
}
14
15
public abstract class InOrder : Order
16
{
17
18
}
19
20
public class OutOrder : Order
21
{
22
public override void Submit()
23
{
24
System.Console.WriteLine("to default Out department");
25
}
26
}
Order定义了抽象的Submit,因此只能定义返回值,方法名称,参数列表和访问修饰。有抽象方法的类一定是抽象类(抽象类不一定需要抽象方法)
子类可以实现抽象方法,比如ShipOrder和OutOrder
子类也可以不实现抽象方法,比如InOrder
金庸同志也同时描述了一个关于abstract的例子,威震天下的独孤九剑就是典型的抽象类型
独孤大侠是绝顶聪明之人,学他的剑法,要旨是在一个‘悟’字,决不在死记硬记。等到通晓了这九剑的剑意,则无所施而不可,便是将全部
变化尽数忘记,也不相干,临敌之际,更是忘记得越干净彻底,越不受原来剑法的拘束。
1
public abstract class AloneSwordsmanship//独孤九剑
2
{
3
4
public abstract void 破剑式();
5
public abstract void 破刀式();
6
public abstract void 破枪式();
7
public abstract void 破鞭式();
8
public abstract void 破索式();
9
public abstract void 破掌式();
10
public abstract void 破气式();
11
}
12
13
public class Feng : AloneSwordsmanship//风清扬继承独孤九剑
14
{
15
16
public override void 破剑式()
17
{
18
}
19
20
public override void 破刀式()
21
{
22
}
23
24
public override void 破枪式()
25
{
26
}
27
28
public override void 破鞭式()
29
{
30
}
31
32
public override void 破索式()
33
{
34
}
35
36
public override void 破掌式()
37
{
38
}
39
40
public override void 破气式()
41
{
42
}
43
}
44
45
public class Chong : Feng//令狐冲继承风清扬
46
{
47
48
}
重写方法override
只可以重写基类为虚拟或抽象的方法
必须有相同的签名、不可以更改访问修饰、不可以更改返回值、不可以更改参数列表、不可以更改方法名称、被重写后的方法一定可以再重写
不能是静态方法static、不能是密封方法
所以严格的来讲,令狐冲从风清扬那里得到的是已经重写后的类,不是抽象方法了,风清扬从独孤九剑那里获取的才是真正的抽象剑法。
当基类中没有定义为虚拟或者抽象的方法时
一般的方法是不允许被override的。不过有时候子类一定要有自己的特色,那怎么办呢?new一个方法。
1
public class OutOrder : Order
2
{
3
public override void Submit()
4
{
5
System.Console.WriteLine("to default Out department");
6
}
7
8
public void Send()
9
{
10
System.Console.WriteLine("Sendto Out department");
11
}
12
}
13
14
public class Delivery : OutOrder
15
{
16
17
public new void Send()
18
{
19
System.Console.WriteLine("Sendto Delivery department");
20
}
21
}
注意OutOrder 定义的Send方法没有可以重写的修饰,但子类Delivery 通过new void Send覆盖了基类的方法,因此请注意下面的调用代码
1
OutOrder outorder = new OutOrder();
2
outorder.Send();//Sendto Out department
3
Delivery delivery = new Delivery();
4
delivery.Send();//Sendto Delivery department
5
outorder = delivery;
6
outorder.Send();//注意:Sendto Out department
当子类用new覆盖了基类的方法时,若引用变量为子类,则运行的是子类的new方法;若引用变量是基类,则运行基类方法。
刚才说到了抽象方法和抽象类,我们要再次提醒,有抽象方法的一定是抽象类,但是抽象类不一定包含抽象方法。
嫁衣神功就是典型的没有抽象方法的抽象类,嫁衣神功的修练者本身不能享用嫁衣神功的威力(类不能实例化),要把功力传给他人(必须有子类继承)
以下是一个没有抽象方法的抽象类的例子:
public abstract class Contract//合同
{
/* public Contract()
{
BillCount++;
}
*/
//抽象类没有必要写构造函数
public string Buyer;//买方
public string Seller;//卖方
protected double CostPrice;//成本价
public double SalePrice;//销售价格
public bool CheckPrice()
{
return SalePrice > CostPrice;
}
}
public class SaleContract : Contract
{
}
被修饰为虚拟的方法,实现是可变的,派生类可以重写基类的虚拟方法,也可以不重写基类的虚拟方法
1
public class Space
2
{
3
4
public static void Main(string[] args)
5
{
6
7
new Order().Submit();//to default department
8
new ShipOrder().Submit();//to default Ship department
9
new InOrder().Submit();//to default department
10
new OutOrder().Submit();//to default Out department /n to default department
11
}
12
}
13
14
15
public class Order
16
{
17
18
public virtual void Submit()
19
{
20
System.Console.WriteLine("to default department");
21
}
22
}
23
24
public class ShipOrder : Order
25
{
26
public override void Submit()
27
{
28
System.Console.WriteLine("to default Ship department");
29
}
30
}
31
32
public class InOrder : Order
33
{
34
35
}
36
37
public class OutOrder : Order
38
{
39
public override void Submit()
40
{
41
System.Console.WriteLine("to default Out department");
42
base.Submit();
43
}
44
}
在以上代码中,基类Order的Submit方法被修饰为virtual的,所以ShipOrder 和OutOrder 可以重新定义Submit的具体实现(用override 关键
字),并且还可以使用关键字base来调用基类的方法。
在讲到方法重写的时候,就必须要了解对象的数据类型转换。
在数据类型中,我们知道 数据容量小的(比如int)可以被安全的转换到数据容量大的(比如long)类型,反之是不安全的。
在对象世界正好相反,数据容量大的(子类)可以被安全的转换到数据容量小的(子类的基类)类型,反之是不安全的。
所以,所有的数据类型,都可以被安全的转为object,就是这个道理。
以下代码演示了对象的数据类型转换
1
Order order = new ShipOrder();//可以,子类转为基类
2
order.Submit();//to default Ship department
3
System.Console.WriteLine("type is {0}", order.GetType());//type is ShipOrder
4
ShipOrder ship = (ShipOrder)order;//可以,order是从ShipOrder转来的,但由于是基类转子类,必须强制类型转换
5
order.Submit();//to default Ship department
6
System.Console.WriteLine("type is {0}", ship.GetType());//type is ShipOrder
7
order = new Order();
8
ship = (ShipOrder)order;//不可以,order中没有ShipOrder的成员,编译正确,运行错误
9
InOrder inorder = new InOrder();
10
ship = (ShipOrder)inorder;//不可以,编译错误
在金庸小说《倚天屠龙记》中描述了virtual方法的含义
只听张三丰问道:“孩儿,你看清楚了没有?”张无忌道:“看清楚了。”张三丰道:“都记得了没有?”张无忌道:“已忘记了一小半。”
张三丰道:“好,那也难为了你。你自己去想想罢。”张无忌低头默想。过了一会,张三丰问道:“现下怎样了?”张无忌道:“已忘记了一
大半。”张三丰画剑成圈,问道:“孩儿,怎样啦?”张无忌道:“还有三招没忘记。”张三丰点点头,放剑归座。张无忌在殿上缓缓踱了一
个圈子,沉思半晌,又缓缓踱了半个圈子,抬起头来,满脸喜色,叫道:“这我可全忘了,忘得乾乾净净的了。”张三丰道:“不坏,不坏!
忘得真快”
1
public class Shadowboxing
2
{
3
public virtual void 白鹤亮翅()
4
{
5
}
6
public virtual void 如封似闭()
7
{
8
}
9
public virtual void 野马分鬃()
10
{
11
}
12
}
13
14
public class Zhang : Shadowboxing//张无忌继承张三丰的拳法
15
{
16
public override void 白鹤亮翅()
17
{
18
19
}
20
21
public override void 如封似闭()
22
{
23
24
}
25
26
}
我们再来看抽象方法abstract
抽象的方法隐含的为虚拟的方法,抽象的方法要求派生类必须重写,抽象的方法没有方法体。
1
public abstract class Order
2
{
3
4
public abstract void Submit();
5
}
6
7
public class ShipOrder : Order
8
{
9
public override void Submit()
10
{
11
System.Console.WriteLine("to default Ship department");
12
}
13
}
14
15
public abstract class InOrder : Order
16
{
17
18
}
19
20
public class OutOrder : Order
21
{
22
public override void Submit()
23
{
24
System.Console.WriteLine("to default Out department");
25
}
26
}
Order定义了抽象的Submit,因此只能定义返回值,方法名称,参数列表和访问修饰。有抽象方法的类一定是抽象类(抽象类不一定需要抽象方法)
子类可以实现抽象方法,比如ShipOrder和OutOrder
子类也可以不实现抽象方法,比如InOrder
金庸同志也同时描述了一个关于abstract的例子,威震天下的独孤九剑就是典型的抽象类型
独孤大侠是绝顶聪明之人,学他的剑法,要旨是在一个‘悟’字,决不在死记硬记。等到通晓了这九剑的剑意,则无所施而不可,便是将全部
变化尽数忘记,也不相干,临敌之际,更是忘记得越干净彻底,越不受原来剑法的拘束。
1
public abstract class AloneSwordsmanship//独孤九剑
2
{
3
4
public abstract void 破剑式();
5
public abstract void 破刀式();
6
public abstract void 破枪式();
7
public abstract void 破鞭式();
8
public abstract void 破索式();
9
public abstract void 破掌式();
10
public abstract void 破气式();
11
}
12
13
public class Feng : AloneSwordsmanship//风清扬继承独孤九剑
14
{
15
16
public override void 破剑式()
17
{
18
}
19
20
public override void 破刀式()
21
{
22
}
23
24
public override void 破枪式()
25
{
26
}
27
28
public override void 破鞭式()
29
{
30
}
31
32
public override void 破索式()
33
{
34
}
35
36
public override void 破掌式()
37
{
38
}
39
40
public override void 破气式()
41
{
42
}
43
}
44
45
public class Chong : Feng//令狐冲继承风清扬
46
{
47
48
}
重写方法override
只可以重写基类为虚拟或抽象的方法
必须有相同的签名、不可以更改访问修饰、不可以更改返回值、不可以更改参数列表、不可以更改方法名称、被重写后的方法一定可以再重写
不能是静态方法static、不能是密封方法
所以严格的来讲,令狐冲从风清扬那里得到的是已经重写后的类,不是抽象方法了,风清扬从独孤九剑那里获取的才是真正的抽象剑法。
当基类中没有定义为虚拟或者抽象的方法时
一般的方法是不允许被override的。不过有时候子类一定要有自己的特色,那怎么办呢?new一个方法。
1
public class OutOrder : Order
2
{
3
public override void Submit()
4
{
5
System.Console.WriteLine("to default Out department");
6
}
7
8
public void Send()
9
{
10
System.Console.WriteLine("Sendto Out department");
11
}
12
}
13
14
public class Delivery : OutOrder
15
{
16
17
public new void Send()
18
{
19
System.Console.WriteLine("Sendto Delivery department");
20
}
21
}
注意OutOrder 定义的Send方法没有可以重写的修饰,但子类Delivery 通过new void Send覆盖了基类的方法,因此请注意下面的调用代码
1
OutOrder outorder = new OutOrder();
2
outorder.Send();//Sendto Out department
3
Delivery delivery = new Delivery();
4
delivery.Send();//Sendto Delivery department
5
outorder = delivery;
6
outorder.Send();//注意:Sendto Out department
当子类用new覆盖了基类的方法时,若引用变量为子类,则运行的是子类的new方法;若引用变量是基类,则运行基类方法。
刚才说到了抽象方法和抽象类,我们要再次提醒,有抽象方法的一定是抽象类,但是抽象类不一定包含抽象方法。
嫁衣神功就是典型的没有抽象方法的抽象类,嫁衣神功的修练者本身不能享用嫁衣神功的威力(类不能实例化),要把功力传给他人(必须有子类继承)
以下是一个没有抽象方法的抽象类的例子:
public abstract class Contract//合同
{
/* public Contract()
{
BillCount++;
}
*/
//抽象类没有必要写构造函数
public string Buyer;//买方
public string Seller;//卖方
protected double CostPrice;//成本价
public double SalePrice;//销售价格
public bool CheckPrice()
{
return SalePrice > CostPrice;
}
}
public class SaleContract : Contract
{
}
相关文章推荐
- 武侠世界中的:虚拟方法、重写方法、抽象方法
- 武侠世界中的:虚拟方法、重写方法、抽象方法
- 虚方法和抽象方法都可以供派生类重写,它们之间有什么区别呢?
- C#基础篇 重写与重载,以及其中设计的虚方法和抽象方法的使用和区别
- C#虚方法、重写方法和抽象方法
- 虚方法、重写方法和抽象方法
- 抽象方法(abstract method) 和 虚方法 (virtual method), 重载(overload) 和 重写(override)的区别于联系
- 面向对象,类的组合关系,继承,实现,方法重写,方法重载,this的使用,抽象方法和抽象类的比较,父类构造方法存在的意义,多态的是用和解析,各种访问修饰符
- 在C#中使用虚方法、重写方法和抽象方法实现表达式运算
- C#:区分:重写、覆盖和重载以及虚方法和抽象方法
- C#基础篇 重写与重载,以及其中设计的虚方法和抽象方法的使用和区别
- A.4-继承,方法重写(覆盖)(override),虚函数(virtaul)和多态,抽象方法和抽象类abstract,密封类(sealed)和密封方法,常量的定义(const)
- C#----虚方法、重写方法和抽象方法
- 虚拟方法和抽象方法有什么区别?
- asp.net 抽象方法和虚方法的用法区别,用Global类重写Application_BeginRequest等方法为例子
- C#基础篇 重写与重载,以及其中设计的虚方法和抽象方法的使用和区别
- 虚方法的重写与普通方法的隐藏的区别;抽象方法和虚方法有什么区别?
- 虚拟方法的重写和静态方法的调用
- 重写equals方法的注意事项
- C#方法重载(overload)方法重写(override)隐藏(new)