asp.net为什么没有多重继承(个人观点,欢迎指正,谢谢!)

具我所知,面向对象规范里并没有反对在具体语言实现多重继承,这里的多重继承举例说:

举个例子,交通工具类可以派生出汽车和船连个子类,但拥有汽车和船共同特性水陆两用汽车就必须继承来自汽车类与船类的共同属性。

如图所示:

 

 用C++的代码示例如下:

 #include <iostream>  


using namespace std;  
  
class Vehicle  
{  
    public:  
        Vehicle(int weight = 0)  
        {  
            Vehicle::weight = weight;  
        }  
        void SetWeight(int weight)  
        {  
            cout<<"重新设置重量"<<endl;  
            Vehicle::weight = weight;  
        }  
        virtual void ShowMe() = 0;  
    protected:  
        int weight;  
};  
class Car:public Vehicle//汽车  
{  
    public:  
        Car(int weight=0,int aird=0):Vehicle(weight)  
        {  
            Car::aird = aird;  
        }  
        void ShowMe()  
        {  
            cout<<"我是汽车!"<<endl;  
        }  
    protected:  
        int aird;  
};  
  
class Boat:public Vehicle//船  
{  
    public:  
        Boat(int weight=0,float tonnage=0):Vehicle(weight)  
        {  
            Boat::tonnage = tonnage;  
        }  
        void ShowMe()  
        {  
            cout<<"我是船!"<<endl;  
        }  
    protected:  
        float tonnage;  
};  
  
class AmphibianCar:public Car,public Boat//水陆两用汽车,多重继承的体现  
{  
    public:  
        AmphibianCar(int weight,int aird,float tonnage)  
        :Vehicle(weight),Car(weight,aird),Boat(weight,tonnage)  
        //多重继承要注意调用基类构造函数  
        {  
          
        }  
        void ShowMe()  
        {  
            cout<<"我是水陆两用汽车!"<<endl;  
        }  
};  
int main()  
{  
    AmphibianCar a(4,200,1.35f);//错误  
    a.SetWeight(3);//错误  
    system("pause");   
}

 上面的代码从表面看,看不出有明显的语发错误,但是它是不能够通过编译的。这是由于多重继承带来的继承的模糊性带来的问题。

先看下图:

 

 在图中深红色标记出来的地方正是主要问题所在,水陆两用汽车类继承了来自Car类与Boat类的属性与方法,Car类与Boat类同为AmphibianCar类的基类,在内存分配上AmphibianCar获得了来自两个类的SetWeight()成员函数,当我们调用a.SetWeight(3)的时候计算机不知道如何选择分别属于两个基类的被重复拥有了的类成员函数SetWeight()。

  由于这种模糊问题的存在同样也导致了AmphibianCar a(4,200,1.35f);执行失败,系统会产生Vehicle”不是基或成员的错误。

而对于以上问题,C++给出的解决方法是虚拟继承的技术。即

在Car类和Boat类继承Vehicle类时,在前面加上virtual关键字就可以实现虚拟继承,使用虚拟继承后,当系统碰到多重继承的时候就会自动先加入一个Vehicle的拷贝,当再次请求一个Vehicle的拷贝的时候就会被忽略,保证继承类成员函数的唯一性。 

代码如下:

#include <iostream>  
using namespace std;  
  
class Vehicle  
{  
    public:  
        Vehicle(int weight = 0)  
        {  
            Vehicle::weight = weight;  
            cout<<"载入Vehicle类构造函数"<<endl;  
        }  
        void SetWeight(int weight)  
        {  
            cout<<"重新设置重量"<<endl;  
            Vehicle::weight = weight;  
        }  
        virtual void ShowMe() = 0;  
    protected:  
        int weight;  
};  
class Car:virtual public Vehicle//汽车,这里是虚拟继承  
{  
    public:  
        Car(int weight=0,int aird=0):Vehicle(weight)  
        {  
            Car::aird = aird;  
            cout<<"载入Car类构造函数"<<endl;  
        }  
        void ShowMe()  
        {  
            cout<<"我是汽车!"<<endl;  
        }  
    protected:  
        int aird;  
};  
  
class Boat:virtual public Vehicle//船,这里是虚拟继承  
{  
    public:  
        Boat(int weight=0,float tonnage=0):Vehicle(weight)  
        {  
            Boat::tonnage = tonnage;  
            cout<<"载入Boat类构造函数"<<endl;  
        }  
        void ShowMe()  
        {  
            cout<<"我是船!"<<endl;  
        }  
    protected:  
        float tonnage;  
};  
  
class AmphibianCar:public Car,public Boat//水陆两用汽车,多重继承的体现  
{  
    public:  
        AmphibianCar(int weight,int aird,float tonnage)  
        :Vehicle(weight),Car(weight,aird),Boat(weight,tonnage)  
        //多重继承要注意调用基类构造函数  
        {  
            cout<<"载入AmphibianCar类构造函数"<<endl;  
        }  
        void ShowMe()  
        {  
            cout<<"我是水陆两用汽车!"<<endl;  
        }  
        void ShowMembers()  
        {  
            cout<<"重量:"<<weight<<"顿,"<<"空气排量:"<<aird<<"CC,"<<"排水量:"<<tonnage<<"顿"<<endl;  
        }  
};  
int main()  
{  
    AmphibianCar a(4,200,1.35f);  
    a.ShowMe();  
    a.ShowMembers();  
    a.SetWeight(3);  
    a.ShowMembers();  
    system("pause");   
} 

再假设如果没有Vehicle这个类,在Car和Boat里都有SetWeight这个方法,那在 AmphibianCar在调用基类的SetWeight时,就要用到C++中的作用域运算符::用于解决作用域冲突的情况下产生的二义性问题。

我们回到Asp.net的情况下,ASP.net是不允许多重继承,也就是说一个类的基类只能有一个,但ASP.net允许了一个类可以实现多个接口。

对于MSDN blog上提供了一些对于为什么没有实现MI机制的解释,引用如下:

There are several reasons we haven't provided a baked-in, verifiable, CLS-compliant version of multiple implementation inheritance:

1. Different languages actually have different expectations for how MI works. For example, how conflicts are resolved and whether duplicate bases are merged or redundant. Before we can implement MI in the CLR, we have to do a survey of all the languages, figure out the common concepts, and decide how to express them in a language-neutral manner. We would also have to decide whether MI belongs in the CLS and what this would mean for languages that don't want this concept (presumably VB.NET, for example). Of course, that's the business we are in as a common language runtime, but we haven't got around to doing it for MI yet.

2. The number of places where MI is truly appropriate is actually quite small. In many cases, multiple interface inheritance can get the job done instead. In other cases, you may be able to use encapsulation and delegation. If we were to add a slightly different construct, like mixins, would that actually be more powerful?

3. Multiple implementation inheritance injects a lot of complexity into the implementation. This complexity impacts casting, layout, dispatch, field access, serialization, identity comparisons, verifiability, reflection, generics, and probably lots of other places. 

大致的意思是指如果要实现MI,实际会给asp.net的实现带来很多复杂的机制,而且还指出,MI的情况在实际情况下比较少出现,大多数情况下还是可以用多接口实现的方式来解决。

我的理解是,必竟,接口是没有实现的,而且好的设计是会遵从接口隔离原则的。 当然,对于以上解释,也有一些人是持以反对态度。在这里,我并不是支持以上说法,

必竟我也是ASP.net使用者中的一员,我只是希望能多一个角度来看待ASP.net。 

原文地址:https://www.cnblogs.com/malaikuangren/p/2442325.html