面向对象三大特点,类的继承

    SEO基础 wuya 80次浏览 已收录 0个评论

    三大特点

    • 封装:既是对数据的封装,又是对处理数据方法的封装。
    • 继承:强调父子类的关系
    • 多态:不同的对象调用相同的方法,有不同的响应

    类的继承

    • 相关概念
      • 继承:父类的属性和方法,子类直接拥有,称为继承。
      • 派生:子类在父类的基础上衍生出的新的特征(属性和行为)。
      • 总结:其实他们是一回事,只是描述问题的侧重点不同(继承侧重相同点,派生侧重不同点)
    • 继承与派生
      • 继承
      # class Animal:
      # 当没有写父类时,默认继承自object类
      class Animal(object):
          def __init__(self, name):
              self.name = name
      
          def run(self):
              print('很多小动物喜欢到处奔跑')
              
      class Dog(Animal):
          pass
      
      d = Dog('旺财')
      
      # 直接拥有父类的属性
      print(d.name)
      
      # 直接拥有父类的方法
      d.run()
    • 派生
      class Animal:
          def run(self):
              print('小动物喜欢到处乱跑')
      
      class Cat(Animal):
          def eat(self):
              print('俺喜欢吃鱼')   
      
      c = Cat()
      
      # 继承自父类的方法
      c.run()
      
      # 衍生的方法
      c.eat()
      
      # 动态添加的属性
      c.name = '加菲'
      print(c.name)  
    • 方法重写
      class Animal:
          def eat(self):
              print('小动物一天到晚吃个不停')
      
          def run(self):
              print('天天到处乱跑')
      
      class Cat(Animal):
          # 完全不合适,需要覆盖重写
          def run(self):
              print('俺走的是猫步')
      
          # 不是完全合适,需要进行修改
          def eat(self):
              # 调用父类的方法
              # Animal.eat(self)        # 不建议使用
              # super(Cat, self).eat()    # 老的写法
              super().eat()               # 新的写法,推荐使用
              print('俺喜欢吃鱼')   
              
      c = Cat()
      
      c.run()
      c.eat()
    • 多继承:一个类可以有多个父类
      • 基本语法
      class A:
          def eat(self):
              print('eat func in class A')
              
      class B:   
          def run(self):
            print('run func in class B')
      
          def eat(self):
              print('eat func in class B')
      
      # 多继承,多个父类之间使用逗号隔开
      class C(A, B):
          def eat(self):
              # 不重写或直接使用super,都是采用的默认继承顺序
              # super().eat()
              # 明确指定调用哪个父类的方法
              B.eat(self)
              
      c = C()
      
      c.eat()
      c.run() 
    • 继承链的顺序
      class A(object):
          def foo(self):
              print('A foo')
              
      class B(object):
          def foo(self):
              print('B foo')
      
          def bar(self):
              print('B bar')
              
      class C1(A, B):
          pass   
          
      class C2(A, B):
          def bar(self):
              print('C2-bar')
              
      class D(C1, C2):
          pass
      
      d = D()
      
      d.foo()
      d.bar()
          
      # __mro__类属性,记录了继承连的查找顺序
      # 一旦找到,立即停止并返回
      # 采用的是广度优先遍历的原则
      for i in D.__mro__:
          print(i)
    • 访问权限
      class Person:
          def __init__(self, name, age):
              self.name = name
              self.age = age
              self.__money = 100
      
          def test(self):
              print('for test', self.__money)
              
      p = Person('王大花', 18)
      
      # 公有属性:在类内、类外以及子类中都可以使用
      print(p.name)
      
      # 私有属性:只能在类的内部使用,类外及子类中都不能使用
      # print(p.__money)
      
       p.test()
      print(p.__dict__)
      
      # 实现:在原有的属性名之前添加了'_类名'的前缀
      # 不建议这样使用
      # print(p._Person__money)
      
      class Man(Person):
          def introduce(self):
              print(self.name, self.age)
              # print(self.__money)
              
      m = Man('二狗', 20)
      print(m.name)
      m.test()
    • 总结:
      • 公有属性:在类的内部、外部、子类中都可以使用
      • 私有属性:只能在类的内部使用,不能在外部及子类中使用
      • 实现原理:默认在以__开头的属性前添加了_类名的前缀
    • 类属性
      class Person:
          # 类属性:通过类名进行访问
          nation = '中国'
      
          # 限制对象可以使用的属性,可以大幅提升访问的效率
          __slots__ = ('name', 'age')
      
          def __init__(self, name):
              self.name = name
              
      xiaoming = Person('小明')
      xiaohong = Person('小红')
      
      print(xiaoming.name)
      print(xiaohong.name)
       
      # 访问类属性,通过类名访问
      print(Person.nation)
      
      # 不要这样使用
      # print(xiaoming.nation)
      
      # 查看对象的类型
      print(xiaoming.class)
      
      # 特殊的类属性
      # 类的名字
      print(Person.__name__)
      
      # 父类组成的元组
      print(Person.__bases__)
      
      # 类相关的信息
      print(Person.__dict__)
      
      # 继承链查找顺序
      print(Person.__mro__)
      
      # print(Person.slots)
      # 不能添加,因为slots中没有改属性
      # xiaoming.weight = 180
    • 类方法
      • 说明:也是通过类名调用,创建时需要使用装饰器classmethod
      • 创建对象或简单的创建对象
      class Person:
          # 成员方法,通过对象调用
          def eat(self):
              print('能吃是福')
      
          # 类方法,通过类名调用
          @classmethod
          def test(cls):
              # cls表示当前类
              print(cls)
      
          # 创建对象 或 简单的创建对象
          @classmethod
          def create(cls):
              p = cls()
              p.age = 1
              return p
          
      p = Person()
      p.eat()
      
      Person.test()
      
      p2 = Person.create()
      print(p2.age, type(p2))
    • 提供简洁易用的对外接口
        class Number:
            def __init__(self, num1, num2):
                self.num1 = num1
                self.num2 = num2
      
            def add(self):
                return self.num1 + self.num2
      
            def sub(self):
                return self.num1 - self.num2
      
            def mul(self):
                return self.num1 * self.num2
      
            def div(self):
                if self.num2 == 0:
                    return None
                return self.num1 / self.num2
      
            @classmethod
            def pingfanghe(cls, num1, num2):
                n1 = cls(num1, num1)
                n12 = n1.mul()
      
                n2 = cls(num2, num2)
                n22 = n2.mul()
      
                n3 = cls(n12, n22)
                return n3.add()
      
      # 直接调用类方法
      print(Number.pingfanghe(3, 4))        
    • 静态方法
      • 说明:也是通过类型调用,使用装饰器staticmethod装饰
      • 示例:
      class Person:
          # 定义静态方法
          @staticmethod
          def test():
              print('for test')
      
          # 可以创建对象
          @staticmethod
          def create():
              p = Person()
              return p
       
      class Man(Person):   
          @staticmethod
          def test():
              # 无法调用父类的方法
              # super().test()
              print('xxx')
              
      Person.test()
      
      p = Person.create()
      print(type(p))
      
      Man.test()
    • 总结
      • 凡是使用静态方法解决的问题都可以使用类方法进行解决
      • 静态方法重写时无法调用父类的方法
      • 静态方法中没有cls的参数

    学海无涯 , 版权所有丨如未注明 , 均为原创丨转载请注明面向对象三大特点,类的继承
    喜欢 (0)
    发表我的评论
    取消评论
    表情 加粗 删除线 居中 斜体 签到

    Hi,您需要填写昵称和邮箱!

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址