类的继承2(多继承,晕啊晕啊晕啊)

此篇接 类的继承-1,这块听得不是很明白,所以展开帖子记录下细节。

6.多继承的时候,父类是从左到右执行的。class Woman(People,Relation), 先执行People,再执行 Relation

话不多说,先上程序。我的疑惑在于:在定义Relation的时候,没有进行__init初始化,为什么可以直接调用self.name和obj.name

1. Man(People,Relation) 执行的时候,先去People里面找构造方法,进行__init的初始化,接着再执行程序,此时self.name=name已经存在,所以Relation中可以调用。

class People(object):
    def __init__(self,name):
        self.name=name

class Relation(object):
    def make_friends(self,obj):
        print("%s is making friend with %s"%(self.name,obj.name))

class Man(People,Relation):
    pass
class Woman(People,Relation):
    pass

m1=Man("Jack")
w1=Woman("Lily")
m1.make_friends(w1)

运行结果:

Jack is making friend with Lily

2.当把People,Relation调换顺序以后,发现程序还是可以正常执行。这是因为在Man(Relation,People)的时候,程序并没有真正开始执行,只是做了一些初始化的工作。

所以此时self.name=name已经存在了。在运行m1.make_friends(w1)的时候,程序才开始真正执行。所以也不会报错。

class People(object):
    def __init__(self,name):
        self.name=name

class Relation(object):
    def make_friends(self,obj):
        print("%s is making friend with %s"%(self.name,obj.name))

class Man(Relation,People):
    pass
class Woman(Relation,People):
    pass

m1=Man("Jack")
w1=Woman("Lily")
m1.make_friends(w1)

运行结果:

Jack is making friend with Lily

3.接着修改函数,让Relation函数初始化的时候同时打印self.name. 此时因为People函数还没有初始化,所以找不到self.name,会报错。

证明当继承多个父类的时候,默认的执行顺序是从左到右执行的。

class People(object):
    def __init__(self,name):
        self.name=name

class Relation(object):
    def __init__(self,n):
        print(self.name)
    def make_friends(self,obj):
        print("%s is making friend with %s"%(self.name,obj.name))

class Man(Relation,People):
    pass
class Woman(Relation,People):
    pass

m1=Man("Jack")
w1=Woman("Lily")
m1.make_friends(w1)

运行结果:

Traceback (most recent call last):
  File "<encoding error>", line 16, in <module>
  File "<encoding error>", line 7, in __init__
AttributeError: ‘Man‘ object has no attribute ‘name‘

4. 想在搞明白obj.name是什么意思了。m1.make_friends(w1) 中传的是w1, obj.name实际上就是w1.name. 而w1.name已经初始化过了,所以不会报错。

不需要再定义obj.name的巧妙之处就在于:传的参数是w1.

class People(object):
    def __init__(self,name):
        self.name=name

class Relation(object):
    def make_friends(self,obj):
        print("%s is making friend with %s"%(self.name,obj.name))

class Man(Relation,People):
    pass
class Woman(Relation,People):
    pass

m1=Man("Jack")
w1=Woman("Lily")
m1.make_friends(w1)
print(w1.name)

运行结果:

Jack is making friend with Lily
<class ‘__main__.Woman‘>
Lily

5.因为Lucy没有经过People的初始化,所以她也没有name属性,所以obj.name会报错。

class People(object):
    def __init__(self,name):
        self.name=name

class Relation(object):
    def make_friends(self,obj):
        print("%s is making friend with %s"%(self.name,obj.name))

class Man(Relation,People):
    pass
class Woman(Relation,People):
    pass

m1=Man("Jack")
w1=Woman("Lily")
m1.make_friends(‘Lucy‘)

运行结果:

Traceback (most recent call last):
  File "<encoding error>", line 16, in <module>
  File "<encoding error>", line 7, in make_friends
AttributeError: ‘str‘ object has no attribute ‘name‘

至此,算是搞明白了。在后面的例子中还需要再慢慢消化。

时间: 2024-08-28 03:36:29

类的继承2(多继承,晕啊晕啊晕啊)的相关文章

类的三大特性,继承

继承: 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 python中的继承分为:单继承和多继承 class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass pass class SubClass2(ParentClass1,P

19._7泛型继承之泛型类继承普通类

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _19._7泛型继承之泛型类继承普通类 { abstract class genClass<T> { protected T field; public virtual T property { get { return field; } } p

JS中“类”继承和原型继承

类继承: 先用函数构造器创建了一个“类”Student,然后在Student原型上定义了一个方法sayHello,然后创建了一个"类“PrimaryStudent,用apply()初始化PrimaryStudent. 然后让PrimaryStudent的原型等于Student创建的对象,并把PrimaryStudent原型上的构造器指向当前”类“,即PrimaryStudent,注意红色加粗部分. 1 function Student(name){ 2 this.name = name; 3 }

C++ - 类的虚函数\虚继承所占的空间

类的虚函数\虚继承所占的空间 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24236469 char占用一个字节, 但不满足4的倍数时, 会进行数据对齐, 使用4的倍数的字节(byte). GCC: GCC中, 不管是虚函数还是虚继承, 都须要将指针存储在虚函数表(virtual function table), 占用4个字节. 继承会继承基类的数据, 和虚函数表, 即继承基类的空间. 代码: /* * test.cpp *

C++中的类继承之单继承&amp;多继承&amp;菱形继承

 C++中的类继承之单继承&多继承&菱形继承 单继承是一般的单一继承,一个子类只 有一个直接父类时称这个继承关系为单继承.这种关系比较简单是一对一的关系: 多继承是指 一个子类有两个或以上直接父类时称这个继承关系为多继承.这种继承方式使一个子类可以继承多个父类的特性.多继承可以看作是单继承的扩展.派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承.多继承下派生类的构造函数与单继承下派生类构造函数相似,它必须同时负责该派生类所有基类构造函数的调用.同时,派生类的参数个数必须包

【整理】C++虚函数及其继承、虚继承类大小

参考文章: http://blog.chinaunix.net/uid-25132162-id-1564955.html http://blog.csdn.net/haoel/article/details/1948051/ 一.虚函数与继承 1.空类,空类单继承,空类多继承的sizeof #include <iostream> using namespace std; class Base1 { }; class Base2 { }; class Derived1:public Base1

类多继承及虚继承探研

多继承产生的问题 #include <iostream> using namespace std; // 多继承产生的问题:如果一个继承的多继承有同一个父类, // 则父类的构造函数会被调用两次 ////////////////////////////////////////////////////////////////////////// // 多继承,多基类混乱的问题 // 以下代码的结果 /* 总类 A 构造函数被调用... 类 A1 构造函数被调用... 总类 A 构造函数被调用..

类设计中几种继承方式

 通过继承能够从已有的类派生出新的类,而派生类继承了基类的特征,包括方法.正如继承一笔财产要比自己白手起家容易一样,通过继承派生出的类通常比设计新类要容易得多.下面是可以通过继承完成的一些工作. ①可以在已有类的基础上添加功能. ②可以给类添加数据. ③可以修改类方法的行为. C++有三种继承方式:公有继承.保护继承和私有继承. 一.公有继承 公有继承是最常用的方式,它建立一种is-a关系,即派生类对象也是一个基类对象,可以对基类对象执行的任何操作,也可以对派生类对象执行. ①公有继承不建立

Lua面向对象----类、继承、多继承、单例的实现

(本文转载)学习之用,侵权立删! 原文地址   http://blog.csdn.net/y_23k_bug/article/details/19965877?utm_source=tuicool&utm_medium=referral lua面向对象实现: 一个类就像是一个创建对象的模具.有些面向对象语言提供了类的概念,在这些语言中每个对象都是某个特定类的实例.lua则没有类的概念,每个对象只能自定义行为和形态.不过,要在lua中模拟类也并不困难. lua中,面向对象是用元表这个机制来实现.

虚继承之单继承的内存布局(VC在编译时会把vfptr放到类的头部,这和Delphi完全一致)

C++2.0以后全面支持虚函数与虚继承,这两个特性的引入为C++增强了不少功能,也引入了不少烦恼.虚函数与虚继承有哪些特性,今天就不记录了,如果能搞了解一下编译器是如何实现虚函数和虚继承,它们在类的内存空间中又是如何布局的,却可以对C++的了解深入不少.这段时间花了一些时间了解这些玩意,搞得偶都,不过总算有些收获,嘿嘿. 先看一段代码class A{      virtual aa(){};}; class B : public virtual  A{      char j[3];