作者toki (いまがその时だ)
看板C_Sharp
标题Re: 虚拟函式的使用
时间Wed Feb 18 01:48:01 2009
※ 引述《atowng (阿棠)》之铭言:
: 书看了一阵子,还是不是很清楚这个东西该怎麽使用,我们说
: public class 父类别
: {
: public virtual int 属性名称
: {
: get{return 0;}
: }
: public virtual string 方法名称();
: }
: public class 子类别 : 父类别
: {
: public new int 属性名称
: {
: get{return 1;}
: }
: public overrde string 方法名称();
: }
: 一个是用"new"去取代原先父类别的成员,一个是使用"overrde"去覆写父类别中的
: 虚拟成员。
: 这边小弟就迷惑了:1.一个类别中可能有许多的成员,一个子类别去继承了它,对於
: 父类别中的虚拟成员,子类别一定要覆写吗?
: 2.我们知道C#中还有抽象类别与介面,也是可以实现物件的多型,这三者之间该怎麽
: 运用适当。
Abstract class 主要用来表达有同样的 property / method / event 的物件
并且这些物件间会有继承的关系,EX:
+--正方形(Square)
+----四边形---+--长方形(Rectangle)
| (Quadrangle)
形状(Shape)----+----三角形-------+--等腰三角形(IsoscelesTriangle)
| (Triangle) |--正三角形(RegularTraiangle)
+----圆形
(Circle)
上面所有的有关形状的 class 都由形状这个 base abstract class 继承而来
假设形状这个 base class 有一个叫「算面积(CalcArea)」的 virtual function
这个「算面积()」的功能在形状这个 class 里绝对算不出来(因为没长宽,也没半径)
但是你知道所有的形状都可以算的出面积
於是你必需在所有继承形状的 class 里实作这个「算面积()」
但是对於程式设计师来说,不管是什麽样的形状,只要继承自形状
都可以操作「形状.算面积()」这个 base class 里的 function 来求出它的面积
范例 code:
Shape a = new Rectangle(width, height);
Shape b = new RegularTriangle(base, height);
double aa = a.CalcArea();
double ba = b.CalcArea();
请注意上面 new 出来的物件是一个 Rectangle,一个 RegularTriagnle
但是都使用 Shape 这个 base class 做操作
再来谈 interface,interface 和 abstract class 不同之处
在於它只是一种标记,只要有这种标记的 class,它就「必需」要「能执行」
该 interface 里所宣告的所有的事项(包括 method, property, event)
也因此 interface 主要用来定立一些共通的操作界面
EX: 汽车喇叭可以按(Push)、贩卖机的按钮也可以按
但显然我们不会用同一个 base class 来描述汽车喇叭和贩卖机
另外一般来说,interface 给人的感觉会很像简易版的抽像类别
但它有以下的不同点
1、interface 里所有被宣告的 property、method、event 都是 public 的
abstract class 里你可以有 private 和 protected 的相关宣告
2、interface 里所有被宣告的 property、method 都必需要被继承且实作才能使用
abstract class 你可以不用实作,因为你可以 new 一个 abstract class
虽然那没什麽意义,但是你没办法直接 new 一个 interface
你必需 new 出继承了该 interface 并实作的 class,
再从那上面取得(Query)该interface
3、interface 在 C# 里可以多重继承,class 只能单一继承
上面看了一定雾杀杀,我用刚刚的 shape 来举例子
像上面所有继承自 Shape 的 class 都可以算面积
也因此我可以宣告一个 interface 叫 ICanCalcArea
里面有一个 CalcArea(),代表含有这个 interface 的 class 都要可以执行
CalcArea() 这件工作
interface ICanCalcArea
{
double CalcArea();
}
也因此
public class Triangle() : ICanCalcArea { ..... }
public class Rectangle() : ICanCalcArea { ..... }
这代三角形和长方形的 class 都可以含有 ICanCalcArea 这个 interface
也就是说它们都可以算面积,那这样和 abstract class 有什麽不一样吗?
我们再加上一个 class
public class Robot() : ICanCalcArea, IRobotAction { ..... }
一个和形状扯不上边的 class -> Robot(机器人) 也可以含有这个 interface
只要它被宣告含有这个 interface,管你是机器人还是火箭,它就是要能够算面积
并且上面的宣告中,Robot这个 class 还含有另一个 IRobotAction 的 interface
这代表 Robot 这个 class 也必需要能执行 IRobotAction 里宣告的工作
而 interface 的使用呼叫上也是有所不同的:
// new 出一个 Rectangle 物件 a
Rectangle a = new Rectangle(Width, Height);
// 从 a 上 query 出 ia 这个 ICanCalcArea 的 interface
ICanCalcArea ia = a as ICanCalcArea;
// 使用 query 出的 ICanCalcArea 的 interface 来执行 CalcArea()
if (ia != null)
double aa = ia.CalcArea();
那 Robot 呢?
Robot b = new Robot(....);
ICanCalcArea ib = b as ICanCalcArea;
if (ib != null)
double ba = ib.CalcArea();
// 接下来 Query 出 IRobotAction 来执行这个 interface 上的工作
IRobotAction irab = b as IRobotAction;
if (irab != null)
irab.自爆(); //执行 IRobotAction 里的 method 自爆
先写到这,有错请帮忙订正
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 122.116.82.44
※ 编辑: toki 来自: 122.116.82.44 (02/18 01:50)
1F:→ FantasyRyu:真是…非常详尽… 02/18 16:44
2F:推 osanaosana:不推怎麽行ㄋ... 02/18 18:03
3F:推 Hikki520:感谢分享~受教了! 02/19 16:41
4F:推 holybible:讲解得非常清楚,推荐! 02/20 23:55