You are currently viewing Class

Class

物件式導向編程

OOP編程是利用“類”和“對象”來創建各種模型來實現對真實世界的描述,使用面向對象編程的原因一方面是因為它可以使程序的維護和擴展變得更簡單,並且可以大大提高程序開發效率 ,另外,基於面向對象的程序可以使它人更加容易理解你的代碼邏輯,從而使團隊開發變得更從容。

面向對象的幾個核心特性如下

  • Class 類
    一個類即是對一類擁有相同屬性的對象的抽象、藍圖、原型。在類中定義了這些對象的都具備的屬性(variables(data))、共同的方法

  • Object 對象
    一個對象即是一個類的實例化後實例,一個類必須經過實例化後方可在程序中調用,一個類可以實例化多個對象,每個對象亦可以有不同的屬性,就像人類是指所有人,每個人是指具體的對象,人與人之前有共性,亦有不同

  • Encapsulation 封裝
    在類中對數據的賦值、內部調用對外部用戶是透明的,這使類變成了一個膠囊或容器,裏面包含著類的數據和方法

  • Inheritance 繼承
    一個類可以派生出子類,在這個父類裏定義的屬性、方法自動被子類繼承

  • Polymorphism 多態
    多態是面向對象的重要特性,簡單點說:“一個接口,多種實現”,指一個基類中派生出了不同的子類,且每個子類在繼承了同樣的方法名的同時又對父類的方法做了不同的實現,這就是同一種事物表現出的多種形態。
    編程其實就是一個將具體世界進行抽象化的過程,多態就是抽象化的一種體現,把一系列具體事物的共同點抽象出來, 再通過這個抽象的事物, 與不同的具體事物進行對話。
    對不同類的對象發出相同的消息將會有不同的行為。比如,你的老板讓所有員工在九點鐘開始工作, 他只要在九點鐘的時候說:“開始工作”即可,而不需要對銷售人員說:“開始銷售工作”,對技術人員說:“開始技術工作”, 因為“員工”是一個抽象的事物, 只要是員工就可以開始工作,他知道這一點就行了。至於每個員工,當然會各司其職,做各自的工作。
    多態允許將子類的對象當作父類的對象使用,某父類型的引用指向其子類型的對象,調用的方法是該子類型的方法。這裏引用和調用方法的代碼編譯前就已經決定了,而引用所指向的對象可以在運行期間動態綁定

Class 類

class Role(object):
    #構造函數,構造方法 == 初始化方法
    def __init__(self,name,role,weapon,life_value=100,money=15000): 
        self.name = name
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money

    # 類的方法
    def shot(self):
        print("shooting...")

    def got_shot(self):
        print("ah...,I got shot...")

    def buy_gun(self,gun_name):
        print("just bought %s" %gun_name)

# r1 -> 實例化後產生的對象叫實例
r1 = Role('Alex','police','AK47') 
# 上述在運行時相當於 Role(r1, 'Alex','police','AK47') 
# 所以在 r1 實例化過程中 self = r1
r2 = Role('Jack','terrorist','B22')  #生成一個角色

Class 公有與私有屬性

class Role(object):
    # 所有經由此類所實例化的實例都可以共同存取的屬性才是公有屬性
    # 在類裡直接定義的屬性即是公有屬性
    nationality = 'JP'

    def __init__(self,name,role,weapon,life_value=100,money=15000):
        # 放在此生成的屬性被稱為成員屬性
        self.name = name # 可以以 r1.name 來存取
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money
        self.__heart = 'Normal' # 私有屬性 無法以 r1.__heart 來存取

    def shot(self):
        print("shooting...")

    def got_shot(self):
        print("ah...,I got shot...")

    def buy_gun(self,gun_name):
        print("just bought %s" %gun_name)
        self.weapon = gun_name

    def get_heart(self): # 對外部提供只讀訪問接口
        return self.__heart 

def shot2(self):
    print('run my own shot method')

# 公有屬性在實例化前就已經存在
print(Role.nationality)

# 實例化 r1、r2
r1 = Role('Alex','police','AK47') 
r2 = Role('Jack','terrorist','B22')
r2.buy_gun("B46")
print(r2.weapon)

# 私有屬性 __private_attr_name = value
# 強制訪問 私有屬性 實例._className__privateValue
print(r1._Role__heart)

# 公有屬性範例
print(r1.nationality)
print(r2.nationality)

Role.nationality = 'US'
print(r1.nationality)
print(r2.nationality)

#  公有屬性私有化
r1.nationality = 'TW'
print(r1.nationality)
print(r2.nationality)

# 私有化方法
r1.shot = shot2
r1.shot(r1)

file

繼承

面向對象編程 (OOP) 語言的一個主要功能就是“繼承”。繼承是指這樣一種能力:它可以使用現有類的所有功能,並在無需重新編寫原來的類的情況下對這些功能進行擴展。

通過繼承創建的新類稱為“子類”或“派生類”。

被繼承的類稱為“基類”、“父類”或“超類”。

繼承的過程,就是從一般到特殊的過程。

要實現繼承,可以通過“繼承”(Inheritance)和“組合”(Composition)來實現。

在某些 OOP 語言中,一個子類可以繼承多個基類。但是一般情況下,一個子類只能有一個基類,要實現多重繼承,可以通過多級繼承來實現。

繼承概念的實現方式主要有2類:實現繼承、接口繼承。

Ø 實現繼承是指使用基類的屬性和方法而無需額外編碼的能力;
Ø 接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力(子類重構爹類方法);
在考慮使用繼承時,有一點需要註意,那就是兩個類之間的關系應該是“屬於”關系。例如,Employee 是一個人,Manager 也是一個人,因此這兩個類都可以繼承 Person 類。但是 Leg 類卻不能繼承 Person 類,因為腿並不是一個人。

抽象類僅定義將由子類創建的一般屬性和方法。
OO開發範式大致為:劃分對象→抽象類→將類組織成為層次化結構(繼承和合成) →用類與實例進行設計和實現幾個階段。

單繼承

#!_*_coding:utf-8_*_
#__author__:"Alex Li"

class SchoolMember(object):
    members = 0 #初始學校人數為0
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def tell(self):
        print("----info:%s----"%self.name)
        for k,v in self.__dict__.items():
            print("\t", k, v)

    def enroll(self):
        '''註冊'''
        SchoolMember.members += 1
        print("\033[32;1mnew member [%s] is enrolled,now there are [%s] members.\033[0m " %(self.name,SchoolMember.members))

    # 當程序結束時,會自動調用 __del__ 方法,也可以自己重構此方法 
    def __del__(self):
        '''析構方法'''
        print("\033[31;1mmember [%s] is dead!\033[0m" %self.name)
        SchoolMember.members -= 1

class Teacher(SchoolMember):
    def __init__(self,name,age,course,salary):
        super(Teacher,self).__init__(name,age) # 先繼承,在重構
        self.course = course
        self.salary = salary
        self.enroll()

    def teaching(self):
        '''講課方法'''
        print("Teacher [%s] is teaching [%s] for class [%s]" %(self.name,self.course,'s12'))

    def tell(self):
        '''自我介紹方法'''
        msg = '''Hi, my name is [%s], works for [%s] as a [%s] teacher !''' %(self.name,'Oldboy', self.course)
        print(msg)

class Student(SchoolMember):
    def __init__(self, name,age,grade,sid):
        #SchoolMember.__init__(self,name,age) # 舊式類寫法
        super(Student,self).__init__(name,age) # 新式類寫法
        self.grade = grade
        self.sid = sid
        self.enroll()

    #def tell(self):
    #    '''自我介紹方法'''
    #    msg = '''Hi, my name is [%s], I'm studying [%s] in [%s]!''' %(self.name, self.grade,'Oldboy')
    #    print(msg)

if __name__ == '__main__':
    t1 = Teacher("Alex",22,'Python',20000)
    t2 = Teacher("TengLan",29,'Linux',3000)

    s1 = Student("Qinghua", 24,"Python S12",1483)
    s2 = Student("SanJiang", 26,"Python S12",1484)

    t1.teaching()
    t2.teaching()
    t1.tell()

    # __dict__ 會以字典形式輸出實例中的所有變數
    print(t1.__dict__)

多繼承

#!_*_coding:utf-8_*_
#__author__:"Alex Li"

class SchoolMember(object):
    members = 0
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def tell(self):
        print("----info:%s----"%self.name)
        for k,v in self.__dict__.items():
            print("\t", k, v)

    def enroll(self):
        '''註冊'''
        SchoolMember.members += 1
        print("\033[32;1mnew member [%s] is enrolled,now there are [%s] members.\033[0m " %(self.name,SchoolMember.members))

    def __del__(self):
        '''析構方法'''
        print("\033[31;1mmember [%s] is dead!\033[0m" %self.name)
        SchoolMember.members -= 1

class School(object):
    '''學校類'''
    def open_branch(self,addr):
        print("openning a new branch in ", addr)

class Teacher(SchoolMember, School):
    def __init__(self,name,age,course,salary):
        super(Teacher,self).__init__(name,age)
        self.course = course
        self.salary = salary
        self.enroll()

    def teaching(self):
        '''講課方法'''
        print("Teacher [%s] is teaching [%s] for class [%s]" %(self.name,self.course,'s12'))

    def tell(self):
        '''自我介紹方法'''
        msg = '''Hi, my name is [%s], works for [%s] as a [%s] teacher !''' %(self.name,'Oldboy', self.course)
        print(msg)

class Student(SchoolMember):
    def __init__(self, name,age,grade,sid):
        super(Student,self).__init__(name,age)
        self.grade = grade
        self.sid = sid
        self.enroll()

if __name__ == '__main__':
    t1 = Teacher("Alex",22,'Python',20000)
    t2 = Teacher("TengLan",29,'Linux',3000)

    s1 = Student("Qinghua", 24,"Python S12",1483)
    s2 = Student("SanJiang", 26,"Python S12",1484)

    t1.open_branch("zh")

多態

多態性(polymorphisn)是允許你將父對象設置成為和一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。
那麽,多態的作用是什麽呢?我們知道,封裝可以隱藏實現細節,使得代碼模塊化;繼承可以擴展已存在的代碼模塊(類);它們的目的都是為了——代碼重用。而多態則是為了實現另一個目的——接口重用!多態的作用,就是為了類在繼承和派生的時候,保證使用“家譜”中任一類的實例的某一屬性時的正確調用。

Pyhon 很多語法都是支持多態的,比如 len(), sorted(), 你給 len 傳字符串就返回字符串的長度,傳列表就返回列表長度。

Python 多態示例

#_*_coding:utf-8_*_

class Animal(object):
    def __init__(self, name):  # Constructor of the class
        self.name = name

    def talk(self):              # Abstract method, defined by convention only
        raise NotImplementedError("Subclass must implement abstract method")

class Cat(Animal):
    def talk(self):
        print('%s: 喵喵喵!' %self.name)

class Dog(Animal):
    def talk(self):
        print('%s: 汪!汪!汪!' %self.name)

def func(obj): #一个接口,多种形态
    obj.talk()

c1 = Cat('小晴')
d1 = Dog('李磊')

func(c1)
func(d1)

Beck Yeh

熱愛學習於 Linux 與 程式設計 在網站中分享各式各樣學習到的新知識

發佈留言

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料