精华内容
下载资源
问答
  • 本文以实例形式较为全面的讲述了C++的多重继承与虚继承,是大家深入学习C++面向对象程序设计所必须要掌握的知识点,具体内容如下: 一、多重继承 我们知道,在单继承中,派生类的对象中包含了基类部分 和 派生类...
  • 主要介绍了C++中的多态与多重继承实现Java的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 多继承与多重继承

    千次阅读 2017-04-22 17:35:59
    什莫是多重继承? 一个类不仅仅有父类还有祖父类 什莫是虚继承? 虚继承是为了解决继承的问题.经过这样的声明后,当基类通过条派生路径被一个派生类继承时,该派生类只继承该基类一次,也就是说,基类成员只保留...

    什莫是多继承?
    一个类拥有两个或者两个以上的父类
    什莫是多重继承?
    一个类不仅仅有父类还有祖父类
    什莫是虚继承?
    虚继承是为了解决多继承的问题.经过这样的声明后,当基类通过多条派生路径被一个派生类继承时,该派生类只继承该基类一次,也就是说,基类成员只保留一次。
    菱形继承:
    以往,在派生类的构造函数中只需负责对其直接基类初始化,再由其直接基类负责对间接基类初始化。现在,由于虚基类在派生类中只有一份数据成员,所以这份数据成员的初始化必须由派生类直接给出。如果不由最后的派生类直接对虚基类初始化,而由虚基类的直接派生类(如类B和类C)对虚基类初始化,就有可能由于在类B和类C的构造函数中对虚基类给出不同的初始化参数而产生矛盾。所以规定:在最后的派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化。
    //由于b,c拥有同一个父类,并且虚继承过来的
    class D: public B, public C
    {
    D(int n):A(n),B(n),C(n){ } //D类构造函数,在初始化列表中对所有基类进行初始化
    };

    展开全文
  • 在本篇文章中我们给大家分析了python继承与多重继承的相关知识点内容,有兴趣的读者们参考下。
  • 二、多重继承    我的理解就是基类生子类,子类再生子类。 例如下面三个类构成一个继承链: Millimeter继承自Centimeter,Centimeter又继承自Meter。 //基类 class Meter { private: float ...

    一、基类指针

    一般的,如果定义一个指向基类类型的指针,那么这种类型的指针具有如下特性:

    • 指向基类对象的指针可以指向其子类对象。
    • 如果子类覆盖了其基类中的函数成员,但通过基类指针所访问的成员仍然是基类的成员,而不是子类的成员

    比如基类BaseClass拥有函数F,其子类ChildClass中覆盖了函数F,那么如下语句将仍然调用A的函数F:

    BaseClass *aptr;    //基类类型的指针
    ChildClass child;
    aptr = &child;      //仍可以指向子类对象
    aptr->F();          //但仍然调用基类的函数F()

    二、多重继承

            我的理解就是基类生子类,子类再生子类。

    例如下面三个类构成一个继承链:

    Millimeter继承自Centimeter,Centimeter又继承自Meter。

    //基类
    class Meter
    {
    private:
        float dataMeter;
    public:
        void setData(float m)
        {
            dataMeter = m;
        }
        float getMeter(){return dataMeter;}
        virtual float getData(){return dataMeter;}
        float dataSquare(){return getData()*getData();}
    };
    //子类
    class Centimeter:public Meter
    {
    private:
        float dataCentimeter;
    public:
        //覆盖基类的setdata
        void setData(float m)
        {
            dataCentimeter = m;
            Meter::setData(dataCentimeter/10.0f);
        }
        float getCentimeter(){return dataCentimeter;}
        virtual float getData(){return dataCentimeter;}
    };
    //测试多重继承
    class Millimeter:public Centimeter
    {
    protected:
        float dataMillimeter;
    public:
        void setData(float mi)
        {
            dataMillimeter = mi;
            Centimeter::setData(dataMillimeter/10.0f);
        }
        float getMillimeter(){return dataMillimeter;}
        virtual float getData(){return dataMillimeter;}
    };

    因为两个子类都覆盖了setData函数,这时如果在主函数中执行下面的语句,将导致连锁的函数调用,每个类的中的数据成员都将被赋予相应的值:

         Millimeter mm;
        cout << "plesase input the mm:";
        float temp;
        cin>>temp;
        mm.setData(temp);    //导致连锁的函数调用,

    三、多继承

    • 上述的继承链是继承的一种方式;
    • 继承的另一种方式是多继承,在这种情况下,一个类有两个或多个父类。
    • 但是多继承遭到很多程序设计人员的批评,并不建议在程序中使用多继承。并且Java语言也已经取消了多继承。单纯的继承链已经能够解决复杂的问题。

    多继承的一般声明为:

    class 子类名:继承修饰符 基类1,继承修饰符 基类2

    比如:

    class ChildClass:public BaseClass1,private BaseClass2

    注意:

    • 多继承时的构造函数的调用顺序实在上面定义时就已经确定了。先调用基类1的构造,再调用基类2的,依次进行。
    • 多继承可能会带来二义性。如果两个基类具有同名函数成员,那么子类中就需要对其进行覆盖,并通过作用域分辨符进行区分。
    展开全文
  • 多重继承与虚基类

    2012-06-13 16:14:04
    c++多重继承与虚基类的ppt 讲细致 易懂
  • C++ 继承(2): 多重继承, 继承, 虚继承(virtual)

    千次阅读 多人点赞 2019-03-20 22:59:49
    C++远征之继承篇 视频教程 笔记 方便自己查阅和复习,温故而知新。 ...4 多继承与多重继承 4.1 多重继承 4.2 继承 代码示例 5 虚继承 代码示例 参考资料 4 多继承与多重继承 4.1...

    C++远征之继承篇 视频教程 笔记 方便自己查阅和复习,温故而知新。

    接着  C++ 继承(1): 继承方式(public, protected, private), 继承中的特殊关系(隐藏 , is-a) 继续做笔记

     

    目录

    4 多继承与多重继承

    4.1  多重继承

    4.2  多继承

    代码示例

    5 虚继承

    代码示例

    参考资料


     

     

    4 多继承与多重继承

    4.1  多重继承

    如下图示,士兵类 继承 人类 , 步兵类 继承 士兵类。我们称之为 这三者 属于 多重继承关系

     

    我们还可以知道 这三者 相互之间 是 is-a 关系

     

    在代码中 可以写为:

     

     

     

    4.2  多继承

    一个类有两个及以上的父类,称之为 多继承。注意区别前面的 多重继承

     

     

    在代码中 形式为:

     

     

    代码示例

    示例1:多重继承
    要求:
    1 定义Person类
        数据成员: m_strName 
        成员函数:构造函数  析构函数 play()

    2 定义Soldier类:
        数据成员: m_iAge
        成员函数:构造函数  析构函数  worker()

    3 定义Infantry类 
        数据成员:无
        成员函数: 构造函数 attack()

    4 定义函数test1(Person p) test2(person &p) test3(Person *p)

    //Person.h
    #pragma once
    #include<iostream>
    #include<string>
    using namespace std;
    
    class Person
    {
    public:
    	Person(string name="pesrson_001");//构造函数
    	virtual ~Person();// virtual 防止内存泄漏
    
    	void play();
    
    protected:
    	string m_strName;
    
    };
    //Person.cpp
    
    #include<iostream>
    #include"Person.h"
    using namespace std;
    
    
    Person::Person(string name)
    {
    	m_strName = name;
    	cout << "Person()--构造" << endl;
    }
    
    Person::~Person()
    {
    	cout << "~Person()--析构" << endl;
    }
    
    void Person::play()
    {
    	cout << "Name: " << m_strName << endl;
    	cout << "Person--play()" << endl;
    }
    
    

     

    //Soldier.h
    
    #pragma once
    #include<iostream>
    #include"Person.h"
    
    class Soldier:public Person
    {
    public:
    	Soldier(string name = "soldier_001", int age = 20);
    	virtual ~Soldier();//virtual 防止内存泄漏
    	void work();
    
    protected:
    	int m_iAge;
    };
    //Soldier.cpp
    
    #include<iostream>
    #include"Soldier.h"
    using namespace std;
    Soldier::Soldier(string name, int age)
    {
    	m_strName = name;
    	m_iAge = age;
    	cout << "Soldier()--构造" << endl;
    }
    
    Soldier::~Soldier()
    {
    	cout << "~Soldier()--析构" << endl;
    }
    
    void Soldier::work()
    {
    	cout << "Name= "<< m_strName << endl;
    	cout << "Age= " << m_iAge << endl;
    	cout << "Soldier--work()" << endl;
    }

     

    //Infantry.h
    #pragma once
    #include"Soldier.h"
    
    class Infantry:public Soldier
    {
    public:
    	Infantry(string name = "Infantry_001", int age = 18);
    	~Infantry();
    
    	void attack();
    };
    
    //Infantry.cpp
    #include"Soldier.h"
    #include"Infantry.h"
    Infantry::Infantry(string name, int age)
    {
    	m_strName = name;
    	m_iAge = age;
    	cout << "Infantry()--构造" << endl;
    }
    
    Infantry::~Infantry()
    {
    	cout << "~Infantry()--析构" << endl;
    }
    
    void Infantry::attack()
    {
    	cout << "Name= " << m_strName << endl;
    	cout << "Age= " << m_iAge << endl;
    	cout << "Infantry--attack()" << endl;
    }

     

     

    //main.cpp
    
    #include<iostream>
    #include"Infantry.h"
    using namespace std;
    /*************************
    多重继承
    要求:
    1 定义Person类
    	数据成员: m_strName 
    	成员函数:构造函数  析构函数 play()
    
    2 定义Soldier类:
    	数据成员: m_iAge
    	成员函数:构造函数  析构函数  worker()
    
    3 定义Infantry类 
    	数据成员:无
    	成员函数: 构造函数 attack()
    
    4 定义函数test1(Person p) test2(person &p) test3(Person *p)
    **************************/
    void test1(Person p)
    {
    	p.play();
    }
    
    void test2(Person &p)
    {
    	p.play();
    }
    
    void test3(Person *p)
    {
    	p->play();
    }
    
    
    
    int main()
    {
    	Infantry infantry;
    	cout << "---------- 1 -----------" << endl;
    	
    	test1(infantry); //产生新的临时对象,函数调用后 自动销毁(调用析构函数)
    
    	cout << "" << endl;
    	cout << "---------- 2 -----------" << endl;
    	cout << "" << endl;
    
    	test2(infantry);
    
    	cout << "" << endl; //没有产生新的临时对象
    	cout << "---------- 3 -----------" << endl;
    	cout << "" << endl;
    
    	test3(&infantry); //没有产生新的临时对象
    
    
    	cin.get();
    	return 0;
    }

    运行结果:

     

     

    示例2: 多继承

    要求:多继承
    1 定义Farmer类
        数据成员: m_strName 
        成员函数:构造函数  析构函数 sow()

    2 定义Worker类:
        数据成员: m_strCode
        成员函数:构造函数  析构函数  carry()

    3 定义MigrantWorker类 
        数据成员:无
        成员函数: 构造函数 析构函数

    //Worker.h
    
    #pragma once
    #include<iostream>
    #include <string>
    using namespace std;
    class Worker
    {
    public:
    	Worker(string code="Worker_001");
    	virtual ~Worker();
    
    	void carry();
    
    protected:
    	string m_strCode;
    };
    //Worker.cpp
    
    #include<iostream>
    #include"Worker.h"
    using namespace std;
    
    Worker::Worker(string code)
    {
    	m_strCode = code;
    	cout << "Worker()--构造" << endl;
    }
    
    Worker::~Worker()
    {
    	cout << "~Worker()--析构" << endl;
    }
    
    void Worker::carry()
    {
    	cout << "Code= " << m_strCode << endl;
    	cout << "Worker--carry()" << endl;
    }
    

     

    //Farmer.h
    
    #pragma once
    #include<iostream>
    #include <string>
    using namespace std;
    class Farmer
    {
    public:
    	Farmer(string name = "Farmer_001");
    	virtual ~Farmer();
    
    	void sow();
    
    protected:
    	string m_strName;
    };
    
    //Farmer.cpp
    #include"Farmer.h"
    using namespace std;
    
    Farmer::Farmer(string name)
    {
    	m_strName = name;
    	cout << "Farmer()--构造" << endl;
    }
    
    Farmer::~Farmer()
    {
    	cout << "~Farmer()--析构" << endl;
    }
    
    void Farmer::sow()
    {
    	cout << "Name= " << m_strName << endl;
    	cout << "Farmer()--sow()" << endl;
    }

     

    //MigrantWorker.h
    #pragma once
    #include<iostream>
    #include <string>
    using namespace std;
    
    #include"Worker.h"
    #include"Farmer.h"
    
    class MigrantWorker:public Worker, public Farmer //继承两个类
    {
    public:
    	MigrantWorker(string name, string code);
    	~MigrantWorker();
    };
    //MigrantWorker.cpp
    
    #include"MigrantWorker.h"
    using namespace std;
    MigrantWorker::MigrantWorker(string name, string code):Farmer(name),Worker(code)
    {
    	cout << "MigrantWorker()--构造" << endl;
    }
    
    
    MigrantWorker::~MigrantWorker()
    {
    	cout << "~MigrantWorker()--析构" << endl;
    }

     

    //main.cpp
    
    #include<iostream>
    #include"MigrantWorker.h"
    using namespace std;
    /*************************
    多继承
    要求:
    1 定义Farmer类
    	数据成员: m_strName 
    	成员函数:构造函数  析构函数 sow()
    
    2 定义Worker类:
    	数据成员: m_strCode
    	成员函数:构造函数  析构函数  carry()
    
    3 定义MigrantWorker类 
    	数据成员:无
    	成员函数: 构造函数 析构函数
    **************************/
    
    int main()
    {
    	MigrantWorker *p = new MigrantWorker("HAHA","002");
    	cout << "---------- 1 -----------" << endl;
    	cout << "" << endl;
    
    	p->carry();
    	p->sow();
    	cout << "---------- 2 -----------" << endl;
    	cout << "" << endl;
    
    	delete p;
    	p = NULL;
    
    
    	cin.get();
    	return 0;
    }
    

     

    运行结果:

     

     

     

     

    5 虚继承

     

     

    上面的这种继承属于菱形继承如果实例化对象D 那么D—>B—>A  D—>C—>A , 此时D将会从A得到两个相同的数据,这属于数据冗余,是不能容忍的。

     

     

    那么菱形继承 需要用 虚继承 来解决数据冗余的问题,格式如下图所示:

     

     

     

     

    代码示例

    要求:虚继承  比较 使用虚继承和 不使用虚继承 之间的区别
    1 定义Farmer类
        数据成员: m_strName
        成员函数:构造函数  析构函数 sow()

    2 定义Worker类:
        数据成员: m_strCode
        成员函数:构造函数  析构函数  carry()

    3 定义MigrantWorker类
        数据成员:无
        成员函数: 构造函数 析构函数

    4 Person 
        数据成员: m_strColor
        成员函数:构造函数  析构函数 printColor()

     

    //Person.h
    #pragma once
    #include<iostream>
    #include<string>
    using namespace std;
    
    class Person
    {
    public:
    	Person(string clolr = "blue");//构造函数
    	virtual ~Person();// virtual 防止内存泄漏
    
    	void printColor();
    
    protected:
    	string m_strColor;
    
    };
    
    //Person.cpp
    
    #include<iostream>
    #include"Person.h"
    using namespace std;
    
    
    Person::Person(string color)
    {
    	m_strColor = color;
    	cout << "Person()--构造" << endl;
    }
    
    Person::~Person()
    {
    	cout << "~Person()--析构" << endl;
    }
    
    void Person::printColor()
    {
    	cout << "Color: " << m_strColor << endl;
    	cout << "Person--printColor()" << endl;
    }
    
    

     

    //Farmer.h
    
    #pragma once
    #include<iostream>
    #include <string>
    #include"Person.h"
    using namespace std;
    class Farmer :public Person
    {
    public:
    	Farmer(string name = "Farmer_001", string color = "blue");
    	virtual ~Farmer();
    
    	void sow();
    
    protected:
    	string m_strName;
    };
    
    
    //Farmer.cpp
    #include"Farmer.h"
    using namespace std;
    
    Farmer::Farmer(string name,string color) :Person("Farmer "+ color)
    
    {
    	m_strName = name;
    	cout << "Farmer()--构造" << endl;
    }
    
    Farmer::~Farmer()
    {
    	cout << "~Farmer()--析构" << endl;
    }
    
    void Farmer::sow()
    {
    	cout << "Name= " << m_strName << endl;
    	cout << "Farmer()--sow()" << endl;
    }

     

     

    //Worker.h
    
    #pragma once
    #include<iostream>
    #include <string>
    #include"Person.h"
    using namespace std;
    class Worker:public Person
    {
    public:
    	Worker(string code = "Worker_001",string color="blue");
    	virtual ~Worker();
    
    	void carry();
    
    protected:
    	string m_strCode;
    };
    
    //Worker.cpp
    
    #include<iostream>
    #include"Worker.h"
    using namespace std;
    
    Worker::Worker(string code,string color):Person("Worker "+ color)
    {
    	m_strCode = code;
    	cout << "Worker()--构造" << endl;
    }
    
    Worker::~Worker()
    {
    	cout << "~Worker()--析构" << endl;
    }
    
    void Worker::carry()
    {
    	cout << "Code= " << m_strCode << endl;
    	cout << "Worker--carry()" << endl;
    }
    
    

     

    //MigrantWorker.h
    #pragma once
    #include<iostream>
    #include <string>
    #include"Worker.h"
    #include"Farmer.h"
    using namespace std;
    
    
    class MigrantWorker :public Worker, public Farmer //继承两个类
    {
    public:
    	MigrantWorker(string name, string code,string color);
    	~MigrantWorker();
    };
    
    //MigrantWorker.cpp
    
    #include"MigrantWorker.h"
    using namespace std;
    MigrantWorker::MigrantWorker(string name, string code,string color) :Farmer(name,color), Worker(code,color)
    {
    	cout << "MigrantWorker()--构造" << endl;
    }
    
    
    MigrantWorker::~MigrantWorker()
    {
    	cout << "~MigrantWorker()--析构" << endl;
    }

     

    //main.cpp
    
    #include<iostream>
    #include"MigrantWorker.h"
    using namespace std;
    /*************************
    
    要求:虚继承  比较 使用虚继承和 不使用虚继承 之间的区别
    1 定义Farmer类
    	数据成员: m_strName
    	成员函数:构造函数  析构函数 sow()
    
    2 定义Worker类:
    	数据成员: m_strCode
    	成员函数:构造函数  析构函数  carry()
    
    3 定义MigrantWorker类
    	数据成员:无
    	成员函数: 构造函数 析构函数
    
    4 Person 
    	数据成员: m_strColor
    	成员函数:构造函数  析构函数 printColor()
    **************************/
    
    int main()
    {
    	MigrantWorker *p = new MigrantWorker("HAHA", "002","black");
    	cout << "---------- 1 -----------" << endl;
    	cout << "" << endl;
    
    	p->Farmer::printColor();
    	cout << "---------- 2 -----------" << endl;
    	p->Worker::printColor();
    
    	cout << "---------- 3 -----------" << endl;
    	cout << "" << endl;
    
    	delete p;
    	p = NULL;
    
    
    	cin.get();
    	return 0;
    }
    
    

     

    上面没有使用虚继承的运行结果:

     

     

     

    接下来 分别 在Farmer.hWorker.h 中加入 virtual 关键字(使用虚继承)

    //Farmer.h  加入虚继承
    
    #pragma once
    #include<iostream>
    #include <string>
    #include"Person.h"
    using namespace std;
    class Farmer :virtual public Person//虚继承
    {
    public:
    	Farmer(string name = "Farmer_001", string color = "blue");
    	virtual ~Farmer();
    
    	void sow();
    
    protected:
    	string m_strName;
    };
    
    
    //Worker.h 加入虚继承
    
    #pragma once
    #include<iostream>
    #include <string>
    #include"Person.h"
    using namespace std;
    class Worker:virtual public Person//虚继承
    {
    public:
    	Worker(string code = "Worker_001",string color="blue");
    	virtual ~Worker();
    
    	void carry();
    
    protected:
    	string m_strCode;
    };
    

     

    运行结果:

     

     


    参考资料

    [1] C++远征之继承篇  (注:图片均来自视频中PPT)

     

    展开全文
  • 多重继承是创建具有个超类的单个类的能力。 其他一些流行的面向对象的编程语言(例如C ++)不同, java不提供对类中多重继承的支持。 Java不支持类中的多重继承,因为它可能导致钻石问题,而不是提供一些复杂的...
    java可以多重继承吗

    java可以多重继承吗

    有时我写了几篇有关Java继承接口组成的文章。 在这篇文章中,我们将研究多重继承,然后了解组成优于继承的好处。

    Java中的多重继承

    多重继承是创建具有多个超类的单个类的能力。 与其他一些流行的面向对象的编程语言(例如C ++)不同, java不提供对类中多重继承的支持。 Java不支持类中的多重继承,因为它可能导致钻石问题,而不是提供一些复杂的方法来解决它,而是有更好的方法来实现与多重继承相同的结果。

    钻石问题

    为了轻松理解钻石问题,我们假定Java中支持多重继承。 在这种情况下,我们可以像下面的图像那样有一个类层次结构。

    钻石问题多重继承

    假设SuperClass是一个抽象类,声明了一些方法,而ClassA,ClassB是具体类。

    超类.java

    package com.journaldev.inheritance;
    
    public abstract class SuperClass {
    
    	public abstract void doSomething();
    }

    ClassA.java

    package com.journaldev.inheritance;
    
    public class ClassA extends SuperClass{
    
    	@Override
    	public void doSomething(){
    		System.out.println("doSomething implementation of A");
    	}
    
    	//ClassA own method
    	public void methodA(){
    
    	}
    }

    ClassB.java

    package com.journaldev.inheritance;
    
    public class ClassB extends SuperClass{
    
    	@Override
    	public void doSomething(){
    		System.out.println("doSomething implementation of B");
    	}
    
    	//ClassB specific method
    	public void methodB(){
    
    	}
    }

    现在,让我们说ClassC的实现如下所示,它扩展了ClassA和ClassB。

    ClassC.java

    package com.journaldev.inheritance;
    
    public class ClassC extends ClassA, ClassB{
    
    	public void test(){
    		//calling super class method
    		doSomething();
    	}
    
    }

    注意, test()方法正在调用超类doSomething()方法,这导致歧义,因为编译器不知道要执行哪个超类方法,并且由于菱形类图,它被称为Diamond Problem,这是Java不支持类中的多重继承的主要原因。

    请注意,具有多个类继承的上述问题也可能只出现在三个类中,它们全部具有至少一个通用方法。

    接口中的多重继承

    您可能已经注意到,我一直在说类不支持多重继承,但是接口支持多重继承,并且单个接口可以扩展多个接口,下面是一个简单的示例。

    接口A.java

    package com.journaldev.inheritance;
    
    public interface InterfaceA {
    
    	public void doSomething();
    }

    接口B.java

    package com.journaldev.inheritance;
    
    public interface InterfaceB {
    
    	public void doSomething();
    }

    注意,两个接口都声明了相同的方法,现在我们可以拥有一个扩展这两个接口的接口,如下所示。

    接口C.java

    package com.journaldev.inheritance;
    
    public interface InterfaceC extends InterfaceA, InterfaceB {
    
    	//same method is declared in InterfaceA and InterfaceB both
    	public void doSomething();
    
    }

    这样做非常好,因为接口仅声明方法,并且实际实现将由实现接口的具体类完成,因此在接口的多重继承中不存在任何歧义的可能性。

    这就是为什么Java类可以实现多重继承的原因,例如下面的示例。

    接口Impl.java

    package com.journaldev.inheritance;
    
    public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC {
    
    	@Override
    	public void doSomething() {
    		System.out.println("doSomething implementation of concrete class");
    	}
    
    	public static void main(String[] args) {
    		InterfaceA objA = new InterfacesImpl();
    		InterfaceB objB = new InterfacesImpl();
    		InterfaceC objC = new InterfacesImpl();
    
    		//all the method calls below are going to same concrete implementation
    		objA.doSomething();
    		objB.doSomething();
    		objC.doSomething();
    	}
    
    }

    您是否注意到,每当我覆盖任何超类方法或实现任何接口方法时,我都使用@Override注释,它是三个内置的Java注释之一,并且 在覆盖任何方法时都应 始终使用覆盖注释

    救援人员组成

    因此,如果我们想在ClassC使用ClassA函数methodA()ClassB函数methodB() ,该解决方案在于使用composition ,这是ClassC的重构版本,该版本使用了composition来利用这两种类方法以及doSomething ()方法来自其中一个对象。

    ClassC.java

    package com.journaldev.inheritance;
    
    public class ClassC{
    
    	ClassA objA = new ClassA();
    	ClassB objB = new ClassB();
    
    	public void test(){
    		objA.doSomething();
    	}
    
    	public void methodA(){
    		objA.methodA();
    	}
    
    	public void methodB(){
    		objB.methodB();
    	}
    }

    组合与继承

    Java编程的最佳实践之一是“通过接口支持组合”,我们将研究一些偏爱这种方法的方面。

    1. 假设我们有一个超类和子类,如下所示:

      ClassC.java

      package com.journaldev.inheritance;
      
      public class ClassC{
      
      	public void methodC(){
      	}
      }

      ClassD.java

      package com.journaldev.inheritance;
      
      public class ClassD extends ClassC{
      
      	public int test(){
      		return 0;
      	}
      }

      上面的代码可以编译并正常工作,但是如果ClassC实现更改如下:

      ClassC.java

      package com.journaldev.inheritance;
      
      public class ClassC{
      
      	public void methodC(){
      	}
      
      	public void test(){
      	}
      }

      请注意,子类中已经存在test()方法,但返回类型有所不同,现在ClassD将无法编译,并且如果您使用的是任何IDE,它将建议您更改超类或子类中的返回类型。

      现在想象一下这样的情况:我们具有多个级别的类继承,并且超类不受我们控制,我们别无选择,只能更改我们的子类方法签名或名称以消除编译错误,我们还必须在所有方面进行更改子类方法被调用的地方,因此继承使我们的代码易碎。

      组合永远不会发生上述问题,这使其比继承更有利。

    2. 继承的另一个问题是,我们将所有超类方法公开给客户端,并且如果我们的超类设计不当且存在安全漏洞,那么即使我们在实现类时全神贯注,我们也会受到不良实现的影响。超类。组合可以帮助我们提供对超类方法的受控访问,而继承不提供对超类方法的任何控制,这也是组合优于继承的主要优势之一。
    3. 组合的另一个好处是它提供了方法调用的灵活性。 我们上ClassC实现不是最佳的,它提供了与将要调用的方法的编译时绑定,只需进行最小的更改,我们就可以使方法调用变得灵活并使其动态。

      ClassC.java

      package com.journaldev.inheritance;
      
      public class ClassC{
      
      	SuperClass obj = null;
      
      	public ClassC(SuperClass o){
      		this.obj = o;
      	}
      	public void test(){
      		obj.doSomething();
      	}
      
      	public static void main(String args[]){
      		ClassC obj1 = new ClassC(new ClassA());
      		ClassC obj2 = new ClassC(new ClassB());
      
      		obj1.test();
      		obj2.test();
      	}
      }

      上面程序的输出是:

      doSomething implementation of A
      doSomething implementation of B

      方法调用的这种灵活性在继承中不可用,并且提倡了最佳做法,即在继承方面偏向于组合。

    4. 单元测试很容易组合,因为我们知道超类中正在使用的所有方法,并且可以对其进行模拟,而在继承中,我们很大程度上依赖于超类,并且不知道将使用所有超类方法,因此我们需要要测试超类的所有方法,这是一项额外的工作,由于继承,我们不需要这样做。

    理想情况下,仅当在所有情况下父类和子类的“ is-a ”关系均成立时才应使用继承,否则我们应该继续进行组合。

    翻译自: https://www.javacodegeeks.com/2013/08/multiple-inheritance-in-java-and-composition-vs-inheritance.html

    java可以多重继承吗

    展开全文
  • 多重继承 概念 多重继承是一个类的父类也有父类。 多重继承的对象初始化方式最高的父类到子类。 A()–&gt;B–&gt;C() 销毁时正好是初始化的反顺序。...多重继承与多继承不同,当B类从A类派生,C...
  • C++ 多重继承

    2021-01-20 13:39:42
    多重继承就是派生类继承个基类,继承方法和一个继承是一样的。 一个继承请看我 —> “C++ 继承和派生” 文章,会有详细介绍。 链接: C++ 继承和派生 在这里我主要讲多重继承的细节。 第一 继承方法: 例如已声明了...
  • C++多重继承继承格式

    千次阅读 2017-10-04 22:48:22
    多重继承 继承格式
  • C++ 多重继承、虚继承与虚基类

    千次阅读 2019-03-22 23:11:14
    类D多重继承类B和C的时候,类A中的数据就会在类D中存在份。通过声明继承关系的时候加上virtual关键字可以实现虚继承。 一、多重继承 单重继承——一个派生类最多只能有一个基类 多重继承——一个派生类可以有...
  • 多重继承继承 这个我们来讲讲这两个的概念问题,一字之差,千差万别。 多重继承,比如有三个类,人类-士兵类-步兵类,三个依次继承,这样的继承称为多重继承。class Person {};class Soldier :public Person {...
  • 多重继承与虚继承

    千次阅读 2013-01-15 09:14:38
    多重继承与虚继承 一、 多重继承 1.定义个类: 图1 多重继承的Panda层次   定义一个抽象 ZooAnimal 类保存所有动物园动物公共信息并提供公用接口,Bear 类将包含 Bear 科的独特信息,以此类推。 除了...
  • 主要介绍了C++多重继承态性原理实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • C++学习之多重继承与虚继承

    千次阅读 2014-07-17 22:40:11
    一、多重继承 我们知道,在单继承中,派生类的对象中包含了基类部分 和 派生类自定义部分。同样的,在多重继承(multiple inheritance)关系中,派生类的对象包含了每个基类的子对象和自定义成员的子对象。下面是一...
  • VC中的多重继承与虚拟继承

    千次阅读 2014-06-01 18:59:32
     多重继承举例
  • 单一继承与多重继承

    千次阅读 2017-08-27 23:06:42
    类的继承就是创建一个具有别的类的属性和行为的新类。即从已有的对象类型出发, 建立一种新的对象类型,使它继承(具有)原对象的特点...这也体现了大自然中一般特殊的关系。继承性很好地解决了软件的可重用性问题。比
  • C++继承多重继承

    千次阅读 2019-03-05 21:58:19
    多重继承:一个基类有一个派生类,这个派生类又有一个派生类 继承:一个派生类有个基类 下面我们看一个多重继承的例子 #include &lt;iostream&gt; #include &lt;stdlib.h&gt; #include ...
  • 继承和多重继承

    2017-05-03 20:28:27
    ------------------siwuxie095                    继承 ... 多重继承,两个词差别不大,但是差之毫厘、谬以千里 … ... 多重继承 ... 如果有这样三个类:人类、士兵类、步兵类,其中:士兵类... 多重继承
  • 继承:一个子类拥有很父类 多重继承 : 一层一层的继承父类 转载于:https://www.cnblogs.com/liunx1109/p/9439424.html
  • 多重继承

    千次阅读 2013-07-15 08:18:23
    多重继承 在面向对象的领域中,对于多重继承的意义、是否需要在C++引入是有争论的(是的!多重继承在纯粹的对象思想看来有些怪异)。基本上撇开对于它的意义的探究,在下面着重阐述的是C++中多重继承的实现技术,以...
  • 主要介绍了java为什么不允许类多重继承却允许接口多重继承,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 多重继承——一个派生类可以有个基类 class 类名: 继承方式 基类1,继承方式 基类2,…. {….}; 派生类同时继承个基类的成员,更好的软件重用 可能会有大量的二义性,个基类中可能包含同名变量或函数 多重...
  • 说说C++多重继承

    2021-01-20 03:40:35
     多重继承是从多于一个直接基类派生类的能力,多重继承的派生类继承其父类的属性。  class ZooAnimal{  };  class Bear : public ZooAnimal{  };  class Endangered{  };  class Panda : public ...
  • python多重继承/继承相关

    千次阅读 2018-07-17 16:52:49
    1 使用父类名....使用类名.__mro__可以查看当前类的多重继承执行顺序,该执行顺序是使用C3算法计算得出。 而C3算法使用的是BFS算法(广度优先搜索算法),在二叉树中表现为尽可能的寻找更分叉。  

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 114,308
精华内容 45,723
关键字:

多重继承与多继承的区别