zoukankan      html  css  js  c++  java
  • 面向对象:继承、多态、封装

    类、对象:

    • 类:抽象的
    • 对象:具体的
    class Person:  # 类名
        def __init__(self, name, hp, aggr, gender):
        # __init__为初始化方法
            self.name = name
            self.hp = hp
            self.aggr = aggr
            self.gender = gender
    
        def walk(self, n):  # 定义方法,一般情况下必须传self参数,且必须写在第一个;后面还可以传其他参数,想传多少就多少
            print("{}走了{}步".format(self.name, n))
    
    p = Person("王者", "100", "5", "")  # 对象 = 类(参数),这个过程叫实例化
    print(p.name)      # 查看属性值
    print(p.__dict__)  # 查看所有属性
    p.walk(10)         # 调用这个对象拥有的方法
    初识类

    类有静态属性和方法,类中的静态属性和方法可以被对象和类调用。

    class Person(object):
        money = 0
    
        def work(self):
            Person.money += 100
    
    mother = Person()
    father = Person()
    mother.work()
    father.work()
    print(Person.money)  #200
    共享静态属性例子

    类的组合:在一个类中以另外一个类的对象作为数据属性

    class Car:
        """一次模拟汽车的简单尝试"""
        def __init__(self, make, model, year):
            self.make = make
            self.model = model
            self.year = year
    
    class Battery:
        """一次模拟电动汽车电瓶的简单尝试"""
        def __init__(self, battery_size=70):
            """初始化电瓶的属性"""
            self.battery_size = battery_size
    
        def describe_battery(self):
            """打印一条描述电瓶容量的消息"""
            print("This car has a " + str(self.battery_size) + "-kWh battery.")
    
    class ElectricCar(Car):
        """电动汽车特殊之处"""
        def __init__(self, make, model, year):
            """初始化父类的属性,再初始化电动汽车特有的属性"""
            super().__init__(make, model, year)
            self.battery = Battery()
    
    my_tesla = ElectricCar("tesla", "model s", 2016)
    my_tesla.battery.describe_battery()  #This car has a 70-kWh battery.
    View Code

    面向对象三大特性:继承、多态、封装

    继承

    继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又称为基类或超类,新建的类这时可称为子类或派生类

    python中类的继承分为:单继承和多继承

      一个类可以被多个类继承
      一个类可以继承多个父类(python独有)

    class A(object):  # 定义父类
        pass
    class B(object):  # 定义父类
        pass
    class C(A):       # 单继承,父类是A,子类是C
        pass
    class D(A,B):     # 多继承(python独有),用逗号分隔开多个继承的类
        pass
    
    ########## 查看继承 ##########
    # __base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
    print(D.__base__)     # <class '__main__.A'>
    print(D.__bases__)    # (<class '__main__.A'>, <class '__main__.B'>)
    
    #在python3中,没有继承父类就默认继承object
    print(A.__bases__)    # (<class 'object'>,)
    继承

    派生

    • 父类中没有的属性,在子类有,叫做派生属性
    • 父类中没有的方法,在子类有,叫做派生方法

    注意:

      子类可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),一旦重新定义了自己的属性且与父类重名,调用时就以自己为准;
      要是子类的对象调用属性,子类中有的名字就用子类的, 子类中没有才找父类的, 如果父类也没有就报错

    在python3中,子类执行父类的方法也可以直接用super方法(super方法只在python3中存在)

    class Base1(object):
        def func(self):
            print("Base1.func")
    
    class Base2(object):
        def func(self):
            print("Base2.func")
    
    class Foo(Base1, Base2):
        def func(self):
            # 方式一:根据mro的顺序执行方法
            super().func()           # Base1.func
            super(Foo, self).func()  # Base1.func
            # 方式二:主动执行父类类的方法
            Base2.func(self)         # Base2.func
            print("Foo.func")
    
    obj = Foo()
    obj.func()              # Foo.func
    super(Foo, obj).func()  # Base1.func  在类外调用父类方法
    
    print(Foo.mro())  # [<class '__main__.Foo'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class 'object'>]

    继承顺序:

    单继承:子类有的用子类,子类没有就用父类
    多继承:
      经典类中:深度优先
      新式类中:广度优先

    python2.7中: 经典类、新式类共存,新式类要继承object
    python3中:    只有新式类,默认继承object

    super的本质(python3才有,即只有新式类,广度优先):不是单纯找父类,而是根据调用者的节点位置的广度优先顺序来的

    class A(object):
        def func(self):
            print("A")
    
    class B(A):
        def func(self):
            super().func()
            print("B")
    
    class C(A):
        def func(self):
            super().func()
            print("C")
    
    class D(B,C):
        def func(self):
            super().func()
            print("D")
    
    d = D()
    d.func()
    print(D.mro())  # mro()方法可查看类的继承顺序
    # [<class "__main__.D">, <class "__main__.B">, <class "__main__.C">, <class "__main__.A">, <class "object">]

    多态

    多态指的是一类事物有多种形态
    动物有多种形态:人、狗、猪

    import abc
    
    class Animal(metaclass=abc.ABCMeta):  # 动物类
        @abc.abstractmethod
        def talk(self):
            pass
    
    class People(Animal):  # 动物的形态之一:人
        def talk(self): 
            print("你好!")
    
    class Dog(Animal):  # 动物的形态之二:狗
        def talk(self):
            print("旺旺!")
    
    class Cat(Animal):  # 动物的形态之三:猫
        def talk(self):
            print("喵喵!")
    View Code
    # 类List与类Tuple都有相似的方法,那么这两个类就是鸭子类型,都可以使用len()方法,而不需要像其他语言一样告诉len()自己是什么类型
    # 在强类型语言中,叫多态
    # 在python中,叫鸭子类型
    
    class List(object):
        def __len__(self):
            pass
    
    class Tuple(object):
        def __len__(self):
            pass
    
    def len(obj):
        return obj.__len__()
    
    l = List()  # 或者T = Tuple()
    len(l)
    鸭子类型

    封装

    隐藏对象的属性和实现细节,仅对外提供公共访问方式。

    好处:
      1.将变化隔离;
      2.便于使用;
      3.提高复用性;
      4.提高安全性。

    封装原则:
      1.将不需要对外提供的内容都隐藏起来;
      2.把属性都隐藏,提供公共方法对其访问。

    在python中用双下划线开头的方式将属性隐藏起来(设置成私有属性)

    class Person:
        __country = "china"   # 私有静态属性
    
        def __init__(self, name, age):
            self.name = name
            self.__age = age  # 私有实例属性
    
        def __get_age(self):  # 私有方法
            return self.__age
    
        def func(self):
            return self.__get_age()  # 调用私有xx的正确方式
    
    p = Person("pd", 18)
    print(p.func())          # 正确使用方式
    # print(p._Person__age)  # 对象._类名__属性名(不建议这样使用!!!)
    私有xx

    封装与扩展性

    封装在于明确区分内外,使得类设计者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.__age = age
    
        def get_age(self):
            return self.__age
    
        def set_age(self, n):
            if 0 < n and n.isdigit():
                self.__age = n
            else:
                return "年龄不合法"
    
    p = Person("pd", 18)
    print(p.get_age())     # 18
    print(p.set_age(-18))  # 年龄不合法
    View Code

    会用到私有的这个概念的场景:

      1.隐藏一个属性,不让类的外部直接调用
      2.保护一个属性,不让属性随意被改变
      3.保护一个属性,不被子类继承

    小结

    接口类、抽象类:
      python中没有接口类,有抽象类,abc模块中的metaclass = ABCMeta,@abstructmethod
      本质是做代码规范用的,希望在子类中实现和父类方法名字完全一样的方法

    接口类与抽象类的区别:
      在java的角度上看是有区别的
        java没有多继承,所以为了接口隔离原则,设计了接口这个概念,以便实现多继承;
        java本来就支持单继承,所以就有了抽象类。
      python既支持单继承也支持多继承,所以对于接口类和抽象类的区别就没有那么明显;python中没有内置接口类

    多态与鸭子类型:
      多态 --> python天生支持多态
      鸭子类型 --> 不依赖父类的情况下实现两个相似的类中的同名方法

  • 相关阅读:
    使用Maven快速创建一个SpringMVC工程步骤
    签到
    yaml简介
    APP定位元素之UiSelector
    js中var、let、const区别
    用Jquery去写树结构
    正则相关的知识分享
    python常见问题
    Vue.js 的一些小技巧
    关于jsp删除成功,添加成功等之后 页面自动跳转的js写法
  • 原文地址:https://www.cnblogs.com/believepd/p/9643471.html
Copyright © 2011-2022 走看看