您的位置:首页 > 其它

.Net平台中虚方法的好处之个人见解

2012-02-07 19:39 211 查看
虽然机房收费系统的代码已经写完了,但是对于.net平台的一些机制的认识还是模模糊糊,记得在学习设计模式的时候就遇到了“虚方法”这个概念,但是对于“虚方法”的认识却好似一团迷雾,今天下午花了一个多小时的时间来研究这个小东东,现在总结一下对“虚方法”的认识,如有不合理之处,望各位大牛们多多斧正。



对于虚方法的官方解释比较复杂,这里就用我的理解来个通俗的解释。虚方法是相对于非虚的方法而言的,两者的区别体现在基类和派生类中的运用上。下面通过网上粘来的一个小例子来说明问题。



class   A 
{ 
      public   void   F()   {   Console.WriteLine( "A.F ");   } 
      public   virtual   void   G()   {   Console.WriteLine( "A.G ");   } 
} 
class   B:   A 
{ 
      new   public   void   F()   {   Console.WriteLine( "B.F ");   } 
      public   override   void   G()   {   Console.WriteLine( "B.G ");   } 
} 
class   Test 
{ 
      static   void   Main()   { 
            B   b   =   new   B(); 
            A   a   =   b; 
            a.F(); 
            b.F(); 
            a.G(); 
            b.G(); 
      } 
}

运行结果是:A.F B.F B.G B.G



先分析一下这个小例子:

在这个例子中,派生类B继承了基类A;在基类A中,包含了一个非虚的方法 F 和一个虚方法 G ;在派生类 B中,引入了一个新的非虚方法 F(重写了父类的实体方法),因为这个方法与基类的非虚方法同名,因此就覆盖了从基类中继承来的方法F,另外在派生类B中还重写了继承来的虚方法 G。(这里网上多数都是说重载,但我觉得应该是重写,因为重载是发生在同一个类中,而重写才是子类与父类间的继承关系,或许重载可泛指重载和重写)



下面是我对运行结果的理解:

首先明白类的继承的一点知识:继承关系中子类可以重写父类里的所有方法,不管父类是不是抽象类,也不管父类中的方法是不是抽象方法。



结合现实生活,分析一下实体方法和虚方法的机制区别:

实体方法(非虚的方法)相当于现实生活中的实体物;虚方法仅相当于一个物体的名字,不具有真实的物质实体。派生类B继承基类A,重写了父类的实体方法和虚方法,但是这两种方法的运行机制是不同的:



虚方法:



相当于现实生活的一个箱子,不管原来这个箱子内部是不是存放着物体(不管基类中的虚方法有没有 默认函数),如果我要往里面重新放了东西的话,这个箱子里装的东西是我最终放进去的物体,这样我在运用箱子这个封装着物体的类(对象)的时候,实际上得到的是里面的物体,而我在需要的时候只需要指定我要用几号箱子即可,这就是.net平台中虚方法的好处,至于好处在程序中的具体运用稍后再谈,这里继续对比实体方法的运行机制。



实体方法:



实体方法好比一个真实的物体的存在,比如说家里有一块铁,父亲(Father)把它炼成了铁锤,而我(Son)却又把这块铁炼成了剑。这里炼铁的方法可用Shape(byval iron as 铁块) as Tool 。当你在实例化的时候,如果指明生成的是父亲类,那么Shape方法得到的就是铁锤,如果实例化的是Son类,那么调用Shape方法则得到一把剑。



对比以上理解,我们不难明白为什么最初的小例子中的运行结果是:A.F(基类实体方法,父亲用铁块炼出了铁锤) B.F (儿子用铁块炼成了) B.G (将A号箱子里放的东西换成B号箱子里的物体,但是标签(箱子号)依然是A,得到的物体是B箱子里的了) B.G (直接就是B号箱子里的物体)



以上用了不少篇幅在分析.net平台的虚方法和实体方法的区别机制,但是.net平台(面向对象编程思想)引入了继承机制,虚、实方法有什么好处?

实体方法很常见,我就不多说了,这里着重结合机房收费系统总结一下虚方法的应用。

我们都知道在D层基本上都是一些增、删、改、查的方法,根据这些共同的地方,我们可以在D层抽象出一个基类(DataBase),专门封装这些公共的方法,然后让具体的D层类来继承这个基类,也就是说在D层的派生类中重写基类的增、删、改、查方法。然后在B层调用的时候只需要实例化D层这个基类,然后再将具体的D层的某个对应实体类的类传给这个基类即可,也就是上面那个例子的B b = new B(); A a =
b; 这样程序在维护的时候就比较容易。

在这里我们肯定会想到D层的辅助类SqlHelp这个类,SqlHelp只是对D层的一些重复的方法,或者代码个隔离,是一些公共的执行动作的封装,与这里的DataBase并不冲突,一个是单纯代码层次的优化,另一个是.net平台机制的合理运用(或是面向对象思想的优点?),两者完全可以结合使用。



另一个问题就是这样一个封装虚方法的DataBase基类和大多数同学运用的D层的接口的设计模式有什么关系?

我认为,这里谈到的是两个不同层次的问题,抽象工厂+配置文件+反射+接口这些组合是利用分层的设计模式将D层和B层解耦,而这里谈到的虚方法可以侧重看成是.net机制的一种技术,好比泛化技术(对接口、类的进一步抽象,也是多态机制的基础)一样,便于代码的优化和程序的维护。



对于虚方法的理解就总结到此,这里只是个人的一些想法,还没有代码实现,上文中如有失当或者错误的地方望多多指导!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: