C#中实现多继承的方法

 更新时间:2020年6月25日 11:35  点击:2327

近日看到了一个贴子,就是在C#语言中,如何实现多继承的问题。相信涉猎c#不多的人(像我这样的菜鸟),一看就觉得很可笑,c#肯定是不能实现多继承的啊。都知道在c++中因为实现多继承会有很多的歧义问题,所以在c#中就把多继承给取消了,而用接口来实现!但是想想,如果是初学者肯定不会不会问这样的问题。肯定是个高手,然后就开始上网查资料!然后发现真的可以实现!

说起多继承,首先大家可以想想这个问题:你知道在C#中怎么实现多继承吗?

主流的答案无非2种。

答案一:用接口啊,一个类可以继承自多个接口的。
答案二:C#不支持多继承,C++才支持多继承,多继承会让代码变得很乱,因此微软在设计C#的时候放弃了多继承。

能够知道答案二的人显然懂的更多,我也在很长一段时间内相信C#不支持多继承,直到2013年5月的一个项目中,我偶然的发现自己的代码就完全实现了真正意义的多继承。

先说说什么是真正意义的多继承。真正的多继承应该是像C++那样的,而不是说像在C#里面一个类继承了多个接口就叫多继承。在C#中,如果一个类实现了多个接口,那么要为每个接口写实现,如果接口被多个类继承,那么就会有重复的代码,这显然是无法接受的。

然而C++那样的多继承也确确实实给编码带来了很大的麻烦,我也相信微软真的是因为意识到了多继承的不合理之处才在C#中摈弃了这个特性。而我在C#中实现的多继承,第一是真正的多继承,第二代码写的很合理。

请看案例

假如你有一个类叫老虎,还有一个类叫苍蝇。现在你想新创一个超级老虎类,一种可以飞的老虎。在C++中,你可以定义一种超级老虎类,让其继承自老虎和苍蝇,这样这种老虎就可以飞了。然而,问题出现了,这种超级老虎由于同时也继承自苍蝇,而苍蝇下面有个方法叫吃,参数类型是屎。吃屎的这个方法显然跟我们的超级老虎太不搭了。

虽然这个例子有些夸张,但是很多C++程序员真的就是这样在设计代码。由于子类继承了多个父类,而多个父类肯定有些成员跟这个子类不搭调,于是子类的调用者就很难受了。比如上面这个例子,当调用者拿到超级老虎的一个实例时,发现超级老虎下面怎么会有个吃屎的方法呢!!!真的是要笑死人了。

C++要这样允许多继承就必然会造成这个问题。C#程序员就绝对不会写出这样滑稽的代码。对于C#程序员,肯定是要把这个飞的方法提成接口的,然后让苍蝇类和超级老虎类都继承自这个接口。这样,苍蝇会飞,超级老虎也会飞。是不是完美解决这个问题?

问题看上去解决了,但是,假如我跟你说苍蝇飞的方法跟超级老虎飞的方法需要一模一样:首先张开双翅,身体前倾,拍打双翅,起飞,继续拍打。我们肯定不能把同一份代码copy一份吧,那是属于入门级程序员干的事,我们现在已经没资格干那事了。那怎么办呢?简单快速的做法是使用静态方法,比如FlyHelper.Fly(...)。

静态方法解决了代码重用的问题,但写起来始终觉得哪里不对劲。我的超级老虎类和苍蝇都明明继承了飞了啊,为什么还要这样调用一句静态方法。如果以后哪天我想让我的猪也能飞起来,那岂不是还要来调用这个静态方法。

到底怎样才能在C#中实现像C++那样优雅的继承呢?

答案揭晓

答案其实很简单,那就是给IFly接口写扩展方法。

首先请看这个空接口的定义,及其扩展方法(注意泛型限制):

复制代码 代码如下:

namespace Interface
{
    //飞的接口
    public interface IFly
    {
    }
    //扩展方法
    public static class ExtendFly
    {
        public static void StartFly<T>(this T example) where T : IFly
        {
            Console.WriteLine("准备");
            Console.WriteLine("张开双翅");
            Console.WriteLine("起飞");
            Console.WriteLine("我飞,我飞,我飞飞飞");
        }
    }
}

再看老虎和苍蝇的实现:

复制代码 代码如下:

namespace Interface
{
    //苍蝇类实现飞的接口
    public class flies : IFly
    {
        public void fly()
        {
            //调用接口中飞的方法
            this.StartFly();
        }
    }
}
namespace Interface
{
    //老虎类
    public class Tiger
    {
        public void introduce()
        {
            Console.WriteLine("I am a tiger");
        }
    }
}

再看超级老虎的实现:

复制代码 代码如下:

namespace Interface
{
    //超级老虎类,继承了老虎类,并实现了飞的方法
    public class SuperTiger : Tiger, IFly
    {
        public override void introduce()
        {
            Console.WriteLine("大家好,我是超级老虎哦!");
        }

        public void TigerFly()
        {
            //调用接口中飞的方法
            this.StartFly();
        }
    }
}

怎么样,你看明白了吗?这个实现是不是很简单呢?好处是不是大大的有呢?

当以后哪天老板让你实现一个会飞的超级猪的话,你只需要让你的超级猪继承“I飞”接口就行了。当哪天老板又不想要这个超级猪飞的话,你也只需要将这个接口继承删掉而已。如果你正在开发一个动物王国程序,你可以将飞的功能注入到任何一种动物身上。想想是不是都觉得很爽。

总结

最后,再让我们回顾一下之前用C++写的超级老虎吃屎的变态例子。这实际上不是C++的错,而是程序员用错了多继承。虽然在语法上C++没有限制程序员怎么去写多继承,但是从上面的例子分析来看,我们很容得出这样一个结论:

当需要写多继承的时候,被继承的父类只能是一个功能,而不应是一个完整的类。

如果按照这个思路,那么今天的这个例子在C++中就可以这样写,首先提一个Flyable的类出来,然后让超级老虎和苍蝇都继承这个Flyable。

在C#中,虽然实现多继承的代码稍微绕了个弯,但是多继承带来的好处是非常明显的:对不同的类实现注入式的功能,让你的代码更符合面向对象的思想。

[!--infotagslink--]

相关文章

  • C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
  • 浅谈C# 字段和属性

    这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
  • C#中截取字符串的的基本方法详解

    这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
  • C#中new的几种用法详解

    本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
  • 使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)

    这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#开发Windows窗体应用程序的简单操作步骤

    这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • 经典实例讲解C#递归算法

    这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • C#绘制曲线图的方法

    这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • c#自带缓存使用方法 c#移除清理缓存

    这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
  • c#中(&&,||)与(&,|)的区别详解

    这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#中list用法实例

    这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25