精华内容
下载资源
问答
  • 考虑用Mix-in组件代替多继承

    万次阅读 2020-10-28 11:24:25
    Python是面向对象的编程语言,它提供了一些内置的编程机制,使得开发者可以适当地实现多继承。但是,我们仍然应该尽量避开多继承。 若一定要利用多继承所带来的便利及封装性,那就考虑编写min-in类。min-in是一种...

    Python是面向对象的编程语言,它提供了一些内置的编程机制,使得开发者可以适当地实现多继承。但是,我们仍然应该尽量避开多继承。

    若一定要利用多继承所带来的便利及封装性,那就考虑编写min-in类。min-in是一种小型的类,它只定义了其他类可能需要提供的一套附加方法,而不定义自己的属性,此外,它也不要求使用者调用自己的__init__构造器。

    min-in的最大优势在于,使用者可以随时安插这些通用的功能,并且在必要时覆写它们,多个min-in直接也可以相互组合。有了这样的min-in之后,我们只需要编写极其少量的代码,就可以通过继承体系,轻松地创建出相关工具类。

    要点:

    1.能用min-in组件实现的效果,就不要用多继承来做。

    2.将各功能实现为可插拔的min-in组件,然后继承之。

    3.将简单的行为封装到min-in组件里,然后就可以用多个min-in组合出复杂的行为。

     

    例如,我们需要把Python实例对象以字典形式输出,以便将其序列化,我们不妨把这个功能写成通用代码,以供其他类使用。

    class ToDictMixin(object):
        def to_dict(self):
            return self._traverse_dict(self.__dict__)
    
        def _traverse_dict(self, instance_dict):
            output = {}
            for key, value in instance_dict.items():
                output[key] = self._traverse(key, value)
            return output
    
        def _traverse(self, key, value):
            if isinstance(value, ToDictMixin):
                return value.to_dict()
            elif isinstance(value, dict):
                return self._traverse_dict(value)
            elif isinstance(value, list):
                return [self._traverse(key, i) for i in value]
            elif hasattr(value, '__dict__'):
                return self._traverse_dict(value.__dict__)
            else:
                return value

    再如,我们可以编写一个min-in,它能为任意类提供通用的JSON序列化功能,我们可以假设:继承了min-in的那个类,会提供名为to_dict的方法。

    class JsonMixin(object):
        @classmethod
        def from_json(cls, data):
            kwargs = json.loads(data)
            return cls(**kwargs)
    
        def to_json(self):
            return json.dumps(self.to_dict())

     然后,我们定义一个测试类,同时继承上述两个min-in,以达到扩展功能的作用。

    class Person(ToDictMixin, JsonMixin):
        def __init__(self, name, age, address, list1, dict1):
            self.name = name
            self.age = age
            self.address = address
            self.list1 = list1
            self.dict1 = dict1
    
        def introduce(self):
            print(f'{self.name} {self.age} {self.address}')

    测试运行结果:

    if __name__ == '__main__':
        # 1.测试ToDictMixin
        person = Person('zhangsan', 18, 'Shenzhen', [1, 2, 3], {'username': 'admin', 'password': '123456'})
        print(person.to_dict())
    
        # 2.测试JsonMixin
        json_str = '{"name": "zhangsan", "age": 18, "address": "Shenzhen", "list1": [1, 2, 3], "dict1": {"username": "admin", "password": "123456"}}'
        person = Person.from_json(data=json_str)
        json_str = person.to_json()
        print(json_str)

    运行结果:

    运行结果显示,已成功为Person类通过min-in扩展的形式,为其添加了新功能 :将Python实例对象以字典形式输出、将Python实例对象以JSON字符串形式输出。

    展开全文
  • Python中类的继承、多层继承和多继承 Python中,一个类可以通过继承的方式来获得父类中的非私有属性和非私有方法。 一、继承、重写、和调用重写的父类方法 继承的语法为在类名后的小括号()中写入要继承的父类名,...

    Python中类的继承、多层继承和多继承

    Python中,一个类可以通过继承的方式来获得父类中的非私有属性和非私有方法。

    一、继承、重写、和调用重写的父类方法

    继承的语法为在类名后的小括号()中写入要继承的父类名,如果要继承多个类则中间用逗号分隔。

    class Electrical(object):
    
        def __init__(self, name):
            self.name = name
    
        def watch_movie(self):
            print('Watch movie!')
    
        def game(self):
            print('Play game!')
    
        def chat(self):
            print('Chat with friend!')
    
    
    class Phone(Electrical, object):
    
        def send_message(self):
            print('Send message!')
    
        def game(self):
            print('Play game in phone!')
    
        def chat(self):
            super(Phone, self).chat()
            print('Chat with anyone!')
    
    
    p = Phone('VIVO')
    # 继承父类的属性
    print(p.name)
    # 继承父类的方法
    p.watch_movie()
    # 子类自己实现的方法
    p.send_message()
    # 重写了父类的方法
    p.game()
    # 先继承父类的方法,在对父类方法的功能进行扩展
    p.chat()

    运行结果:

    VIVO
    Watch movie!
    Send message!
    Play game in phone!
    Chat with friend!
    Chat with anyone!

    1.父类的非私有属性和非私有方法子类可以直接继承,子类对象可以直接使用。如果子类要调用父类的私有属性和私有方法,只能通过间接的方法来获取。

    2.子类可以实现父类没有的属性和方法,与继承的属性和方法互不干扰。

    3.如果在子类中有跟父类同名的方法,但方法中执行的内容不同,则子类可以重写父类方法。

    当子类实现一个和父类同名的方法时,叫做重写父类方法直接在子类中定义与父类同名的方法,然后在方法中实现子类的业务逻辑,子类方法就会覆盖父类的同名方法。子类重写了父类方法,子类再调用该方法将不会执行父类的方法。

    4.如果在子类重写父类的方法中,需要使用父类同名方法中的功能,在父类功能基础上做扩展,则子类可以在重写的方法中调用父类被重写的方法,使用super()来调用。

    二、类的多层继承

    类可以多层继承。

    class Mi(Phone):
        pass
    
    
    m = Mi('Redmi')
    print(m.name)
    m.chat()

    运行结果:

    Redmi
    Chat with friend!
    Chat with anyone!

    继续上面的类,我们定义的类Mi继承自Phone类,Phone类继承自Electrical类,这样就构成了多层继承。

    Mi类对象可以使用Phone中的方法和属性,也可以使用Electrical中的方法和属性,如果Phone重写了Electrical的方法,则继承的是Phone中的方法。

    当Mi类对象调用属性和方法时,优先在自己的内部查找是否有该属性和方法,如果没有会到它的父类Phone中查找该属性和方法,如果没有会继续往上在Phone的父类Electrical中查找,一直查找到object类中。到最后也没有找到,就说明对象没有该属性和方法,程序报错,如果找到就会返回找到的属性和方法,不再继续往上查找。

    三、类的多继承

    class Computer(Electrical):
    
        def coding(self):
            print('Coding something!')
    
    
    class HuaWei(Phone, Computer):
        pass
    
    
    h = HuaWei('huawei')
    h.send_message()
    h.coding()
    print(h.name)
    h.watch_movie()

    运行结果:

    Send message!
    Coding something!
    huawei
    Watch movie!

    同一个类可以继承多个类,如上面的HuaWei类同时继承了Phone和Computer两个类。这时,两个父类中的方法和属性子类都可以使用,两个父类的父类中的属性和方法子类也可以使用。

     

     

     

    展开全文
  • 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)

     

    展开全文
  • 一个子类可以继承多个父类,就是多继承,并且拥有所有父类的属性和方法。 例如 孩子会继承自己的父亲和母亲的特征。 目录 (一)语法 (二)多继承注意事项 (三)钻石继承 (四)多继承中super本质 (一)...

    一个子类可以继承多个父类,就是多继承,并且拥有所有父类的属性和方法。

    例如 孩子会继承自己的父亲和母亲的特征。

    目录

    (一)语法

    (二)多继承注意事项

    (三)钻石继承

    (四)多继承中super本质


    (一)语法

    class 子类名(父类名1,父类名2…) : pass

    (二)多继承注意事项

    如果子类和父类有相同的方法,就会调用子类中的方法。

    如果不同的父类中存在着相同的方法名称,子类对象调用的时候会调用哪个父类中的方法呢? Python会根据 MRO(method resolution order) 方法解析顺序列表进行查找。

    提示:开发时,需要避免这种容易产生混淆的情况!--如果父类之间存在同名的属性和方法,应尽量避免使用多继承。

    以下代码可以确定就近原则:

    class A(object):
    
        def test1(self):
            print('A test1')
    
        def test2(self):
            print('A test2')
    
    
    class B(object):
    
        def test1(self):
            print('B test1')
    
        def test4(self):
            print('B test4')
    
    
    class C(A, B):
        pass
    
    
    # 父类有相同的方法的时候调用哪一个父类的?
    c = C()
    c.test1()
    print(C.mro())  # 使用 mro()方法 来查看类的搜索路径
    print(C.__mro__)  # 与上式一样作用
    """
    [<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
    [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    
    """
    

    (三)钻石继承

    python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有父类的线性顺序列表,例如

    为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。

    而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

    1.子类会先于父类被检查

    2.多个父类会根据它们在列表中的顺序被检查

    3.如果对下一个类存在两个合法的选择,选择第一个父类

    注意:D类有两个选择,默认选择B类执行。

    在Python2.3之前,MRO是基于深度优先算法的,自2.3开始使用C3算法广度优先,定义类时需要继承object,这样的类称为新式类,否则为旧式类。下图左为旧式,右为新。

    只有在python3中才有 __mro__ 和 mor() 方法。

     

    (四)多继承中super本质

     

    不是直接查找父类,而是根据调用节点的广度优先顺序执行的。

    下面看一个例子:

    创建ABCD类,D类继承B,C类,B类继承A类,C类继承A类。

    在每个方法中都调用super().func()方法,查看执行顺序。

    解析:d.func一开始执行,就找MRO列表【D、B、C、A】中前面的类D,在D中遇到super.func()时就找D的父类(有B和C,选哪个?),规定就是按照MRO列表【D、B、C、A】, 所以查B再查C,B和C都有super().func,继续找A,最后A-->C-->B-->D

    进行方法返回就好了。

    展开全文
  • jinja2的多继承和多层继承

    千次阅读 2017-09-05 20:14:54
    jinja2的多继承和多层继承。{{ super() }}
  • Python多继承与super使用详解

    万次阅读 多人点赞 2018-08-17 12:51:38
    Python虽然支持多继承,但是python支持的多继承也是有限的。 0.问题的提出 如果不同的父类中存在同名的方法,子类对象在调用方法时,会调用哪一个父类中的方法呢? Python 中的 MRO —— 方法搜索顺序 Python中...
  • java单继承和多继承

    千次阅读 2019-10-04 19:55:27
    java单继承和多继承 单线程:一个子类只能继承自一个父类 多线程:一个子类可以继承自多个父类 java继承关键字extend和implement,Java所有子类都继承自 java.lang.Object,即java.lang.Object是Java的祖先类,当一...
  • C++多继承多重继承

    千次阅读 2019-03-05 21:58:19
    多继承:一个派生类有多个基类 下面我们看一个多重继承的例子 #include &lt;iostream&gt; #include &lt;stdlib.h&gt; #include &lt;string&gt; using namespace std; /** * 定义人类...
  • C++多继承与虚继承

    千次阅读 2018-12-06 08:57:08
    多继承与虚继承以及存在的问题 例子 多继承与虚继承以及存在的问题 虚继承 有了多继承,虚继承才会有意义 如果有个菱形结构的继承,爷爷类为A,然后B,C是A的派生类,最后D是B和C的派生类, 如果在A中有一个...
  • C++多继承

    千次阅读 2019-03-06 10:12:32
    在C++语言中,一个派生类可以从一个基类派生,也可以从...从多个基类派生的继承称为多继承。 1.继承的三种方式 公有继承(public),私有继承(private),保护继承(protected) 三种继承方式的说明,如下表所示: 2...
  • 多继承与多重继承

    千次阅读 2017-04-22 17:35:59
    什莫是多继承? 一个类拥有两个或者两个以上的父类 什莫是多重继承? 一个类不仅仅有父类还有祖父类 什莫是虚继承? 虚继承是为了解决多继承的问题.经过这样的声明后,当基类通过多条派生路径被一个派生类继承时,该...
  • maven多继承和继承链

    千次阅读 2017-06-22 18:04:33
    maven多继承和继承链 一个工程需要继承多个父工程
  • Java的继承分为接口继承和对象继承,对象继承不能使用多继承,那么为什么Java自己的类可以多继承
  • Java中可实现多继承的三种方法 多层继承 内部类 接口 多层继承 我们知道,如果要直接继承类,子类不可直接多继承,但可通过多层继承实现多继承。但多层继承一般建议不超过三次,且代码较冗余。 //多层继承实现...
  • 多重继承 多继承格式
  • python_单继承与多继承

    千次阅读 2019-06-05 19:30:16
    单继承与多继承? 单继承:一个类只能继承一个父类的方式。 多继承:一个类可以继承多个父类的方式。 单继承:(生物角度) 人类->哺乳类动物->动物->生物->有机物… 多继承:(社会角度) 舞蹈老师(教...
  • 继承:单继承,多继承(有python有多继承,java没有) 类:经典类,新式类 新式类:凡是继承object类都是新式类 python3X 中所有的类都是新式类,因为python3x中的类都默认继承object 经典类:不继承object类都是新式类...
  • C++ 类(多继承和虚继承)

    万次阅读 2018-07-29 16:00:46
    多继承的定义以及多继承的语法; 虚继承; 多继承的定义以及多继承的语法 a. 一个类有多个基类,这样的继承关系称为多继承; b. 多继承声明语法: class 派生类名: 访问控制符 基类名1,访问控制符 基类名2 { ...
  • Python类的继承与多继承

    千次阅读 2019-08-11 15:17:28
    Python类的继承与多继承 继承 两个中有大量重复的代码,是否能够只写一次 ?抽象出一个更抽象的类,放公共代码 通过继承能够重用代码,方便代码的管理和修改 继承并不是复制变量空间,子类更新成员变量,但是父类的...
  • PHP 多继承实现

    千次阅读 2019-11-15 14:58:38
    //不支持的原因跟其他语言的原因相同: 如java 都是多继承带来的菱形继承问题(又叫钻石问题) 详细解释: 假设类 B 和类 C 继承自类 A,且都重写了类 A 中的同一个方法,而类 D ...
  • C++ 多继承

    千次阅读 2017-04-27 13:01:15
     在多继承中,如果直接基类有公共的基类,则会出现重复继承。这样,公共基类中的数据成员在多继承的派生类中皆有多个拷贝。  如:  class A { int x; }; class B: public A{}; class C: publ
  • java如何实现多继承

    万次阅读 热门讨论 2018-09-03 16:26:00
    使用内部类就可以多继承,严格来说,还不是实现多继承,但是这种方法可以实现多继承所需的功能,所以把它称为实现了多继承。 下面就举个例子: 假如有一个打电话类Call,里面实现了一个可以打电话的功能的方法...
  • 深度剖析单继承与多继承

    千次阅读 2018-04-22 21:24:06
    常见的继承分为单继承和多继承,而从这两个分支又可以扩展出很多种情 况。所以,我把继承中最常见也最实用的几种方式总结在下面,希望可以对你们产生帮助。 前言 继承的关系是由人类的血缘关系衍生出来的一个名词,...
  • C++学习之继承篇(多继承与多重继承)

    万次阅读 多人点赞 2016-01-21 18:55:41
    1.多继承 多继承是指一个子类继承多个父类。多继承对父类的个数没有限制,继承方式可以是公共继承、保护继承和私有继承, 不写继承方式,默认是private继承 多继承举例: #include #include #include ...
  • Android Application 多继承

    千次阅读 2017-12-22 17:35:07
    Android Application 多继承 首先,附上Demo链接:https://github.com/EshelGuo/AppMultipleExtends/tree/master  众所周知,Java里的继承都是单继承,而我们今天的话题是通过反射实现Application多继承。那么为...
  • Java 实现“多继承

    万次阅读 2019-07-20 12:49:19
    一、Java语言特点 Java是一种简单、面向对象、分布式、易读、鲁棒、安全、结构明晰、可移植、高性能、多线程、动态的语言。...多继承:指一个子类同时继承多个父类,从而具备多个父类的特征 多继承会造成 ...
  • 类之间仅单继承,不能多继承 解释:子类如果能继承多个父类,如果多个父类中存在同名属性或者方法,子类继承时将不能判断继承自哪个父类的属性和方法,所以类之间不能多继承。 接口之间可以多继承 解释:接口中的...
  • 多重继承和多继承 这个我们来讲讲这两个的概念问题,一字之差,千差万别。 多重继承,比如有三个类,人类-士兵类-步兵类,三个依次继承,这样的继承称为多重继承。class Person {};class Soldier :public Person {...
  • 1.单继承与多继承 2.菱形继承 3.虚继承---解决菱形继承的二义性和数据冗余的问题 4.虚函数与多态 5.继承体系同名函数的关系   1.单继承与多继承  1.1单继承:  一个子类只有一个直接父类。   class Person...
  • Python面向对象——继承和多继承

    千次阅读 2018-07-31 21:13:32
    单继承: 面向对象的主要好处就是代码的重用,实现这一特点通过继承,继承创建的新类...下面我们开始来讲解继承和多继承 首先我们创建两个类, 父类:Father类 子类:Child 父类中属性为money,和一个方法pla...

空空如也

空空如也

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

多继承