zoukankan      html  css  js  c++  java
  • python面向对象三大特性之一继承、多态、封装

    继承,即在定义一个类时,以另一个类为参数,则称这个新定义的类继承了参数类,父类又称为基类。

    单继承表示只继承一个类,多继承表示继承多个类。

    class parent1:
        pass
    class parent2:
        pass
    class sub1(parent1):#单继承
        pass
    class sub2(parent1,parent2):#多继承
        pass

    1.子类继承了父类的所有属性,可以调用父类的属性。

    2.如果在子类中定义了与父类中相同的属性,相当于在自己的属性字典中增加了这些属性,而不是覆盖了父类的这些属性。

    继承具有两种含义:

    1.继承基类的方法,并且做出自己的改变或扩展(代码重用),不建议使用,会让子类与父类出现耦合。

    2.声明某个子类继承于于某基类,定义一个接口,子类继承接口类,并且实现接口中定义的方法,接口就是一个函数。

    即在父类中定义方法但是不指明接口的实现过程,子类继承这个接口并且指明的实现过程。

    定义接口需要导入abc模块,并且在定义基类时添加metaclass=abc.ABCMeta,再在接口前用@abc.abstractmethod修饰即可。

    import abc
    class animal(metaclass=abc.ABCMeta): #定义基类时加metaclass=abc.ABCMeta参数
        def __init__(self,name,leg):
            self.name=name
            self.leg=leg
        @abc.abstractmethod  #在接口前面加@abc.abstractmethod
        def eat_food(self):
            pass
    
    class cat(animal): #def eat_food(self): #print('eat food') cat1=cat('cat1',4) #报错信息Can't instantiate abstract class cat with abstract methods eat_food

    如上述例子,cat类继承了animal类,在不具体化eat_food接口的情况下实例化会报错,去掉两行注释、即指定eat_food方法后才正常。

    对于经典类,多继承情况下,会按照深度优先方式进行查找。

    对于新式类,多继承情况下,会按照深度广度方式进行查找。python3都是新式类。

    class a:
        pass
        def test(self):
            print('a')
    class b(a):
        pass
        # def test(self):
        #     print('b')
    class c(a):
        pass
        # def test(self):
        #     print('c')
    class d(a):
        def test(self):
            print('d')
    class e(b):
        pass
        # def test(self):
        #     print('e')
    class f(c):
        pass
        # def test(self):
        #     print('f')
    class g(d):
        pass
        # def test(self):
        #     print('g')
    class h(e,f,g):
        pass
        # def test(self):
        #     print('h')
    print(h.__mro__)
    h1=h()
    h1.test()  #h-->e-->b-->f-->c-->g-->d-->a

    上述例子,a为基类,b、c、d继承a,e继承b,f继承c,g继承d,h继承e、f、g

    可通过类的__mor__属性(经典类没有这个属性)查看类的继承顺序,结果为一个元组(<class '__main__.h'>, <class '__main__.e'>, <class '__main__.b'>, <class '__main__.f'>, <class '__main__.c'>, <class '__main__.g'>, <class '__main__.d'>, <class '__main__.a'>, <class 'object'>)

    多态,即不同的实例调用类的方法,得到不同的结果。

    class water:
        def __init__(self,temperature):
            self.temperature=temperature
        def get_status(self):
            if self.temperature<0:
                print('The water of %s℃ is slolid ice'%self.temperature)
            elif self.temperature>0 and self.temperature<100:
                print('The water of %s is liquid water'%self.temperature)
            elif self.temperature>100:
                print('The water of %s is gas' % self.temperature)
    
    w1=water(-3)
    w2=water(19)
    w3=water(109)
    w1.get_status()
    w2.get_status()
    w3.get_status()

    封装

    某个事物的数据属性和函数属性作为一个类,这个一个层面的封装。

    类里面的属性使用_开头,这是python与使用者的约定,表示这个属性不应该被除类以外的实例使用,但只是约定,实例还是可以访问。如果在其他模块中通过import * 导入类,以_开头的属性不能被导入和调用,但是直接导入该属性还是可以使用的。

    类里面的属性使用__开头,python会自动将这个属性重命名为_类名__属性名,实例不能直接通过原来的属性名访问,但是还是可以通过系统重命名后的名字访问。

    class cat:
        _type='animal'  #以_开头的属性
        __living='earth'  #以__开头的属性
        def __init__(self,name,leg,tail):
            self.name = name
            self.leg = leg
            self.tail = tail
        def eat(self,food):
            print('%s likes to eat %s'%(self.name,food))
    
    cat1=cat('cat1',4,1)
    print(cat.__dict__)    #{'__module__': '__main__', '_type': 'animal', '_cat__living': 'earth', '__init__':……
    print(cat1._type)  #以_开头的属性可以直接访问
    #print(cat1.__living),会报错'cat' object has no attribute '__living'
    print(cat1._cat__living)  #以__开头的属性可通过重命名后的名字访问
  • 相关阅读:
    关于UITapGestureRecognizer的一些问题
    自定义导航栏返回按钮
    mousewheel滚轮事件 浏览器的写法
    Apache日志不记录图片文件设置方法和来源日志的配置
    redis持久化配置
    haproxy实现负载均衡
    Keepalived高可用软件的安装与配置
    Sublime text2用户自定义配置
    判断各版本的最简写法
    Ubuntu防火墙 UFW 设置
  • 原文地址:https://www.cnblogs.com/Forever77/p/10090403.html
Copyright © 2011-2022 走看看