1. 程式人生 > 其它 >21.面向物件三大特徵 21.繼承與抽象 屬性的查詢順序 派生與覆蓋 子類訪問父類 初始化方法 必須呼叫super 組合 多繼承

21.面向物件三大特徵 21.繼承與抽象 屬性的查詢順序 派生與覆蓋 子類訪問父類 初始化方法 必須呼叫super 組合 多繼承

OOP三大特徵

1.OOP 面向物件 三大特徵

    封裝
    繼承
    多型


1.繼承
什麼是繼承
  繼承是一種關係,描述兩個物件之間,什麼是什麼的關係

  例如麥兜,佩奇,豬剛鬣 都是豬啊,

在程式中,繼承描述的是類和類之間的關係

例如a繼承了b, a就能直接使用b已經存在的方法和屬性

a稱之為子類,b稱之為父類,也稱之為基類

2.為什麼要使用繼承
    繼承的一方可以直接使用被繼承一方已經有的東西

    其目的是為了重用已經有的程式碼,提高重用性

## 如何使用繼承

語法:

class 類名稱(父類的名稱):
    類的內容

#在python中 一個子類可以同時繼承多個父類
2.抽象 不具體 不清晰 很模糊 看不懂 將多個子類中相同的部分,進行抽取,形成新的類,這個過程也稱為 抽象的 過程 正確的使用繼承 1.先抽象再繼承 2.繼承一個已經現存的類,擴充套件或是修改原始的功能 3.屬性的查詢順序 物件自己的 - > 所在類中 -> 找父類 - >父類的父類 ->Object 4.派生 與 覆蓋 派生: 當一個子類中出現與父類中不同內容時,這個子類就稱為派生類 通常子類都會寫一些新的程式碼,不可能和父類完全一樣 , 既通常都是派生類, 所以派生類指的就是子類 覆蓋 也稱之為重寫 overriders 當子類出現了與父類名稱完全一致的屬性或是方法
6.子類訪問父類的內容 語法: 方式1: super(當前類名稱,self).你要調的父類的屬性或方法 方式2: super().你要調的父類的屬性或方法 方式3: 類名稱.你要調的父類的屬性或方法(self) #方式3與繼承無關 #### 強調在強調: 當你繼承一個現有的類,並且你覆蓋了父類的init方法時,必須在初始化方法的第一行呼叫父類的初始化方法,並傳入父類所需的引數 8.組合 也是一種關係,描述兩個物件之間 是什麼有什麼的關係 例如,學生有手機 ,遊戲中角色擁有某些裝備 將一個物件作為另一個物件的屬性,(既什麼有什麼) 組合的目的:也是為了重用現有程式碼 什麼時候使用繼承:分析兩個類的關係,到底是不是:什麼是什麼的關係 什麼時候使用組合:如果兩個類之間 沒有太大的關係,完全不屬於同類 另外組合相比繼承,耦合度更低了 瞭解知識點
## 菱形繼承 首先明確python支援多繼承 ##### 補充:新式類與經典類 python3中任何類都是直接或間接繼承了Object 新式類,任何顯式或隱式地繼承自object的類就稱之為新式類, python3中全都是新式類 經典類,既不是Object的子類 ,僅在python2中出現 當出現了菱形繼承時,新式類,先深度,當遇到了共同父類時就廣度 ​ 新式類,就是深度優先 ​ # 小結: 1.繼承是什麼 2.為什麼用繼承 3.語法 4.先抽象在繼承 6.派生 7.覆蓋 8.子類訪問父類的屬性或方法 super ().名字 ​ 如果你繼承一個已有的類,並且你覆蓋了init 一定要先呼叫父類的init 9.繼承的原理,mro列表 10,新式類與經典類 11.菱形繼承 瞭解 12,屬性的查詢順序
OOP三大特徵
class Base:
    desc = "這是一個基類"

    def show_info(self):
        print(self.desc)

    def make_money(self):
        print("明天立馬找到工作")

# 指定父類 位 Base
class SubClass(Base):
    pass

#即使類中什麼都沒有也可以使用父類中已有的內容
obj = SubClass()
obj.make_money()
print(obj.desc)
1.繼承的基本語法.py
# 抽取老師和學生中相同的部分形成person類

class Person:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

    def say_hi(self):
        print("name:%s,age:%s,gender:%s" % (self.name,self.age,self.gender))


class Teacher(Person):
    def teacher(self):
        print("老師教學生,寫程式碼....")

t1 = Teacher('jack',20,'male')
t1.say_hi()

class Student(Person):
    pass

stu1 = Student('rose',18,'female')
stu1.say_hi()
2.繼承與抽象.py
class A:
    text = "haha"

class B(A):
    text = "heihei"
    pass

b = B()
b.text = "xixi"
print(b.text)
3.屬性查詢順序.py
class Person:
    def say_hi(self):
        print("hello")



class Student(Person):
    def say_hi(self):
        print("hello world!")

stu = Student()
stu.say_hi()
4.派生與覆蓋.py
"""
需求 實現一個能夠限制元素型別的列表類

"""

class MyList(list):
    def __init__(self,element_type):
        super().__init__() # # 呼叫父類的初始化方法 來完成基本的初始化
        self.element_type = element_type

    def append(self, object):
         """

         :param object: 是要儲存的元素
         :return: 沒有
         """
         if type(object) == self.element_type:
                # 我們需要在這裡訪問父類的append函式來完成真正的儲存操作
            super(MyList,self).append(object)
         else:
             print("sorry sir ,you element type not is %s" % self.element_type)



# 建立是指定要儲存的元素型別
m = MyList(int)
# 當你有需求,是需要在建立物件時 乾點什麼事兒  那就該想到初始化方法

m.append(1)
print(m[0])
m.append("12223")
5.實現一個可以限制元素型別的列表.py
class Parent:
    text = 'abc'

    def say_something(self):
        print("anything")


class Sub(Parent):
    def show_info(self):
        print(super(Sub,self).text,1)
        print(super(Sub,self).say_something())

        # 訪問方式2  py3的新語法 最常用的方式
        print(super().text,2)
        super().say_something()

        # 方式3 直接指定類名呼叫
        print(Parent.text)
        Parent.say_something(self)

sub = Sub()
sub.show_info()
6.子類訪問父類的內容.py
# class Person:
#     def __init__(self,name,gender,age):
#         self.name = name
#         self.gender = gender
#         self.age = age
#
#     def say_hi(self):
#         print("name:%s ,gender:%s,age:%s" % (self.name,self.gender,self.age))
#
# class Student(Person):
#     def __init__(self,name,gender,age,number):
#         super().__init__(name,gender,age)
#         self.number = number
#     def say_hi(self):
#         super().say_hi()
#         print("number:%s" % self.number)
#
#
# stu = Student("rose","mael",20,"old01")
# stu.say_hi()

# 為什麼要在初始化方法中呼叫 父類的初始化方法
class Person:
    def __init__(self,name,gender,age,*args):
        self.name = name
        self.gender = gender
        self.age = age
        self.aa()

    def aa(self):
         print("aa run")

    def say_hi(self):
        print("name:%s ,gender:%s,age:%s" % (self.name,self.gender,self.age))


class Student(Person):

    def __init__(self,name,gender,age,number):
        super().__init__(name,gender,age)
        self.number= number

    def say_hi(self):
        super().say_hi()
        print("numnber:%s" % self.number)

stu = Student("rose", "mael", 20, "old01")
stu.say_hi()
7.初始化方法必須呼叫super.py
class Phone:
    def __init__(self,price,kind,color):
        self.price = price
        self.kind = kind
        self.color = color

    def call(self):
        print("正在呼叫XXXX;")

    def send_message(self):
        print("正在傳送簡訊....")


class Student:
    def __init__(self,name,gender,phone):
        self.name = name
        self.gender = gender
        self.phone = phone

    def show_info(self):
        print("name:%s gender:%s" % (self.name,self.gender))

phone = Phone(1000,"apple","red")

stu1 = Student("rose","male",phone)
stu1.phone.call()
8.組合.py
# # coding:utf-8
# class A:
#     pass
#
# class B:
#     pass
#
# class C:
#     pass
#
# class Test(A,B,C):
#     pass
#
# print(Test.mro())
"""
[<class '__main__.Test'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]
"""
# class A(object):
#     pass
#
# print(A.mro()) # [<class '__main__.A'>, <class 'object'>]
#
# print(A.__dict__)
"""
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
"""
# 菱形繼承
# class A:
#     j = 1
#     pass
#
# class B:
#     # j = 2
#     pass
#
# class C(A):
#     # j = 3
#     pass
#
# class D(A):
#     j = 4
#     pass
#
# class E(B,C,D):
#     # j = 5
#     pass
#
# d = E()
# print(d.j)
class B:
    # num = 2
    pass

class C:
    # num = 3
    pass


class E(B):
    # num = 5
    pass

class F(C):
    # num = 6
    pass

class G(C):
    num = 7
    pass

class H(E,F,G):
    # num = 8
    pass

print(H.num)
# print(H.mro())

#[H,E,B,F,G,C,object]
9.多繼承.py

抽象

菱形繼承的查詢順序