一、封装

'''
面向对象中的封装:将属性属性私有化,通过设置共有方法来设置和获取该属性的值
    1.python 中属性私有化:在属性前添加两个下划线
    2.私有属性的操作接口可以自定义set属性()和get属性()方法
    3.python则通过@property装饰器实现 私有属性的操作接口
'''
class Person(object):
    
    def __init(self,name,age):
        self.__name = name;
        self.__age = age
    
    # 自定义get和set 方法实现对私有属性的操作
    def getName(self):
        return self.__name
    
    def setName(self,name):
        self.__name = name

    #使用 @property 装饰器 实现
    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self,age):
         self.__age = age
    '''
    @property说明:
        1.将成员函数的访问 变成对 成员属性的访问 例如:
            p = Person('zhangsan',18)
            p.age 实际上 是访问成员函数age
        2.给私有属性提供访问接口 @property 和 XX.setter(XX 一般为私有属性名称去掉下划线) 成对                
          出现,用于获取值和赋值
        
    '''
'''
属性和方法被私有化之后 只能在当前类中被访问,方法的私有化,同属性的私有化即在方法名之前添加两个下划线
'''
'''
__new__() 方法使用:
    1.该方法为实例化对象时第一个调用的方法。
    2.该方法若设置返回值为 对象实例,则在该方法调用完成之后,接着调用__init__()方法,否则将不调用__init__() 方法 
'''

class Person(obbject):

    def __init__(self,name,age):
        self.__name = name
        self.__age = age

    def __new__(cls,*args,**kwargs):
        print("new 方法被执行了")

二、继承

'''
单继承:一个子类只有一个父类
    claas 父类类名(object):
        父类类体
    class 子类类名(父类类名):
        子类类体
'''
class Person(object):
    

    def __init__(self,name,age):
        self.name = name
        self.age = age

class Student(Person):
     
    def __init__(self,name,age,num):
        
        # 调用父类构造函数
        #方式一: super(当前类名,self).__init__(属性列表)
        # super(Student,self).__init__(name,age)
        #方式二:父类类名.__init__(self,属性列表)
        #Person.__init__(self,name,age)
        # 方式三:super().__init__(属性列表)
        super().__init__(name,age)

        self.num = num
'''
    说明:
        1.在子类不显示的定义__init__,会将父类中的构造函数继承
        2.如果在子类中显式定义了构造函数__init__,则如果需要使用父类中的实例属性
    继承的特点:
        a.子类对象可以直接访问父类中未被私有化的属性
        b.若父类中的属性被私有化,则可以通过@property 接口进行间接访问
        c.子类对象可以调用父类中未被私有化的成员函数
        d.父类的对象无法访问子类特有的属性和成员函数
'''
    
'''
多继承:一个子类有多个父类
语法:class 父类1(object):
        pass
    class 父类2(object):
        pass
    class 子类(父类1,父类2):
        pass
'''
class Father(object):
    pass
class Mother(object):
    pass
class Son(Father,Mother):
    pass
'''
    1.子类若继承多个父类,子类没有显示 定义子类构造函数,则创建子类对象的时候,默认调用第一个父类的构造函数,若子类显示 定义构造函数 则在 子类构造函数中 通过 父类名称.__init__(self) 指定要构造哪个父类对象
    2.多继承中,子类调用父类 重名的构造函数,若通过supper().重名函数名(列表) 则默认调用  第一个继承类 若通过父类名称.重名函数名(参数列表) 调用 则是调用指定的父类成员函数
 
'''

三、多态

'''
多态的前提是继承
    定义时的类和运行时的类型不一致,或者不确定该变量的类型是什么类型,只有当运行
    的时候才能确定该变量的类型
'''

class Person(object):

    def feedAnimal(self,animal): #只有在运行时候才知道是哪个animal的子类
        animal.eat()

class Animal(object):
    
    def __init__(self,name):
        self.name = name
    
    def eat(self):
        print("eating")

class Dog(Animal):
    pass

class Cat(Animal):
    pass

四.继承树

class Base(object):
    def __init__(self):
        print("inter" +"Base" * 10 )
        print("*" * 10)
        print("outer" + "Base" * 10)

class A(Base):
    def __init__(self):
        print("inter" + "A" * 10)
        super().__init__()
        print("outer" + "A" * 10)

class B(A):
    def __init__(self):
        print("inter" + "B" * 10)
        super().__init__()
        print("outer" + "B" * 10)

class C(A):
    def __init__(self):
        print("inter" + "C" * 10)
        super().__init__()
        print("outer" + "C" * 10)


class D(B,C):
    pass

if __name__ == "__main__":
    d = D()

'''
继承关系为:
    Base
     |
     A
    / \
   B   C
    \ /
     D
解析顺序为:
    interBBBBBBBBBB
    interCCCCCCCCCC
    interAAAAAAAAAA
    interBaseBaseBaseBaseBaseBaseBaseBaseBaseBase
    **********
    outerBaseBaseBaseBaseBaseBaseBaseBaseBaseBase
    outerAAAAAAAAAA
    outerCCCCCCCCCC
    outerBBBBBBBBBB

    由此不难看出:python3 继承树中 类的解析规则 为 广度优先解析规则,而在python2中则按照深度优先规则解析
'''