四、第六 - 類的特性講解

類的特性::封裝、繼承、多態。 「一個接口,多種實現」css

類的特性講解

一、類的封裝
做用防止內部對象數據不能被外部隨意修改;使外部程序不須要關注對象內部的構造,只須要經過對象對外提供的接口進行訪問。可分爲類的公有屬性、私有屬性。python

把功能實現的細節不對外暴露;linux

私有屬性:(對外部是不可見的、對內部是可見的)
__private_attr_name = value
def get_heart(self) #對外部提供只讀訪問接口編程

return self.__heart
r1._Role__heart :強制訪問私有屬性ide

 

公有屬性:
在類裏面定義的方法,叫作公有屬性 模塊化

 

 二、類的繼承函數

     1)、類的繼承講解ui

  面向對象編程(OOP) 語言的一個主要功能就是「繼承」。繼承是指這樣一種能力:它可使用現有類的全部功能,並在無需從新編寫原來的類的狀況下對這些功能進行擴展。使用繼承時,有一點須要注意,那就是兩個類之間的關係應該是「屬於」關係編碼

定義:
  一、經過繼承建立的新類稱爲「子類」或「派生類」。
  二、被繼承的類稱爲「基類」、「父類」或「超類」。
  三、繼承的過程,就是從通常到特殊的過程。
 要實現繼承,能夠經過「繼承」(Inheritance)和「組合」(Composition)來實現。一個子類能夠繼承多個基類。可是通常狀況下,一個子類只能有一個基類,要實現多重繼承,能夠經過多級繼承來實現。(注意:建議最多就是三層。)url

繼承概念的實現方式主要有2類:實現繼承、接口繼承。
  一、實現繼承是指使用基類的屬性和方法而無需額外編碼的能力;
  二、接口繼承是指僅使用屬性和方法的名稱、可是子類必須提供實現的能力(子類重構爹類方法);

 面向對象編程開發範式大體爲:劃分對象→抽象類→將類組織成爲層次化結構(繼承和合成) →用類與實例進行設計和實現幾個階段

舉例:

A、簡單例子類的繼承:

class Person(object): #定義類

    def talk(name): #類的調用方法
        print("Who's Talking? It's me.-- %s " % name)

class BlckPerson(Person): #簡單的子類調用父類
      pass

b = BlckPerson
b.talk("chen") #直接調用父類中的方法
輸出:
Who's Talking? It's me.-- chen 

 B、類繼承中,父類與子類中 self 中參數傳遞:由子類中self 傳參到 父類 中。

#conding:utf-8
class Person(object): #定義類
    def __init__(self,name,age):
        self.name = name
        self.age = age
        self.other = "normal"

    def talk(self): #類的調用方法
        print("Who's Talking? It's me.-- %s " % self.name)

class BlckPerson(Person): #簡單的子類調用父類
      def __init__(self,name,age,height):
          Person.__init__(self,name,age) #把父類的公有屬性,也定義繼承過來。
          self.height = height

      def size(self):
          print ("%s 身高是 %s" % (self.name,self.height))

b = BlckPerson('chen1203',25,'180cm') #調用類並傳值。
b.talk() #直接調用父類中的方
b.size()   #在子類中,沒有定義self.name,繼承父類後,能夠直接調用
輸出:
Who's Talking? It's me.-- chen1203 
chen1203 身高是 180cm

 C、類的單繼承示例(複雜度高點)

class SchoolMember(object):

    member = 0

    '''定義共同類別'''
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        self.enroll()

    def enroll(self):
        '''註冊'''
        print ("A New School Member Enrolled ,It's Name: %s" % self.name)
        SchoolMember.member += 1

    def tell(self):
        '''打印信息'''
        print("----------%s-------" % self.name)
        for k,v in  self.__dict__.items():
            print(k,v)
        print("-----END-----")

    """
    def __del__(self): #析構函數
        '''開除學生'''
        print('開除[%s]' % self.name)
        self.member -= 1  
    """
    
class Tearcher(SchoolMember):
    '''老師'''
    def __init__(self,name,age,sex,salary,course):
        SchoolMember.__init__(self,name,age,sex) #經典類的調用
        self.salary = salary
        self.course = course

    def Tearching(self):
        print("Teacher [%s] is tearching [%s] " % self.name,self.course)

class Students(SchoolMember):
    '''' 學生'''
    def __init__(self,name,age,sex,course,fee):
        SchoolMember.__init__(self,name,age,sex)
        self.course = course
        self.fee = fee
        self.amount = 0

    def pay_fee(self,amount):
        print('student [%s] has just paied [%s]' % (self.name, amount))
        self.amount += amount

T1 = Tearcher('chen1203',25,'M',2000,"PHP")
T1.tell()
S1 = Students('jianhui', 30, 'M', 'python', 3000)
S1.tell()
S2 = Students('huaming', 22, 'M', 'python', 1000)
S2.tell()
print(SchoolMember.member)

輸出:
A New School Member Enrolled ,It's Name: chen1203
----------chen1203-------
course PHP
sex M
salary 2000
name chen1203
age 25
-----END-----
A New School Member Enrolled ,It's Name: jianhui
----------jianhui-------
fee 30000
course python
sex M
amount 0
name jianhui
age 30
-----END-----
A New School Member Enrolled ,It's Name: huaming
----------huaming-------
fee 1000
course python
sex M
amount 0
name huaming
age 22
-----END-----
會員總數:3

D、類的多繼承示例(用的很少,通常都是使用單繼承)。有些語言可能不支持,但Python是支持的

接着跟上面的例子,舉例以下:

class SchoolMember(object):  

    member = 0

    '''定義共同類別'''
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        self.enroll()

    def enroll(self):
        '''註冊'''
        print ("A New School Member Enrolled ,It's Name: %s" % self.name)
        SchoolMember.member += 1

    def tell(self):
        '''打印信息'''
        print("----------%s-------" % self.name)
        for k,v in  self.__dict__.items():
            print(k,v)
        print("-----END-----")

    """
    def __del__(self): #析構函數
        '''開除學生'''
        print('開除[%s]' % self.name)
        self.member -= 1  
    """

class School(object):
    def open_branch(self,addr):
        print ("Opening a new branch in ",addr)

class Tearcher(SchoolMember,School):  #把以上的兩個類進行繼承。主要在這個位置進行添加
    '''老師'''
    def __init__(self,name,age,sex,salary,course):
        SchoolMember.__init__(self,name,age,sex) #經典類的調用
        self.salary = salary
        self.course = course

    def Tearching(self):
        print("Teacher [%s] is tearching [%s] " % self.name,self.course)

class Students(SchoolMember,School):
    '''' 學生'''
    def __init__(self,name,age,sex,course,fee):
        SchoolMember.__init__(self,name,age,sex)
        self.course = course
        self.fee = fee
        self.amount = 0

    def pay_fee(self,amount):
        print('student [%s] has just paied [%s]' % (self.name, amount))
        self.amount += amount

T1 = Tearcher('chen1203',25,'M',2000,"PHP")
S1 = Students('jianhui', 30, 'M', 'python', 30000)
S2 = Students('huaming', 22, 'M', 'python', 1000)
S1.open_branch("廣州")

輸出:

A New School Member Enrolled ,It's Name: chen1203
A New School Member Enrolled ,It's Name: jianhui
A New School Member Enrolled ,It's Name: huaming
Opening a new branch in  廣州
類的多繼承

2)、新式類與經典類

Python 2.x中默認都是經典類,只有顯式繼承了object纔是新式類
Python 3.x中默認都是新式類,沒必要顯式的繼承object
注意:之後的使用中,最好統一使用新式類,調用也是用super的方法

新式類與經典類的區別

語法區別:(新的寫法中,都是會按照新式類的寫法來走)
class Persion(object): #新式類
class Persion: #經典類

調用方法的區別:(針對類的多繼承中的例子)
SchoolMember.__init__(self,name,age,sex)#經典類的調用
super(Tearcher,self).__init__(name,age,sex) #新式類的調用

繼承搜索的順序發生了改變:
@ 經典類多繼承屬性搜索順序: 先深刻繼承樹左側,再返回,開始找右側;
@ 新式類多繼承屬性搜索順序: 先水平搜索,而後再向上移動 

A、新式類與經典類的區別:新式類對象能夠直接經過__class__屬性獲取自身類型:type 

舉例:

"""python 3 中執行"""

# -*- coding:utf-8 -*-
class E:
    #經典類
    pass

class E1(object):
    #新式類
    pass

e = E()
print ("經典類")
print (e)
print (type(e))
print (e.__class__)

e1 = E1()
print ("新式類")
print (e1)
print (type(e1))
print (e1.__class__)

輸出:
經典類
<__main__.E object at 0x102978748>
<class '__main__.E'>
<class '__main__.E'>
新式類
<__main__.E1 object at 0x102978828>
<class '__main__.E1'>
<class '__main__.E1'>

====================================

"""python 2 中執行"""

# -*- coding:utf-8 -*-
class E:
    #經典類
    pass

class E1(object):
    #新式類
    pass

e = E()
print ("經典類")
print (e)
print (type(e))
print (e.__class__)

e1 = E1()
print ("新式類")
print (e1)
print (type(e1))
print (e1.__class__)

輸出:

經典類
<__main__.E instance at 0x10b431cb0>
<type 'instance'>
__main__.E
新式類
<__main__.E1 object at 0x10b420250>
<class '__main__.E1'>
<class '__main__.E1'>



結論:新式類對象能夠直接經過__class__屬性獲取自身類型:type ;在python 3 中經典類與新式類是一致的。python2 的輸出中,區別比較大
經典類VS新式類的區別

B、新式類與經典類的繼承搜索的順序區別

舉例說明:

 

(1)、經典類與新式類在python3中的執行順序是:新式類與經典類都是 D->B、C->A(先水平搜索,而後再向上移動)

舉例以下:

 1 """ python3中執行"""
 2 """新式類"""
 3 class A(object):
 4     def __init__(self):
 5         self.n = "A"
 6 
 7 class B(A):
 8    pass
 9 
10 class C(A):
11     def __init__(self):
12         self.n = "C"
13 
14 class D(B,C):
15     pass
16 
17 d = D()
18 print(d.n)
19 
20 """經典類"""
21 class A1:
22     def __init__(self):
23         self.n = "A1"
24 
25 class B1(A1):
26    pass
27 
28 class C1(A1):
29     def __init__(self):
30         self.n = "C1"
31 
32 class D1(B1,C1):
33     pass
34 
35 d1 = D1()
36 print(d1.n)
37 
38 輸出:
39 C
40 C1
python3中執行

(2)、經典類與新式類在python2中的執行順序是:新式類是 D->B、C->A (先水平搜索,而後再向上移動);經典類是 D->B->A-C 或者是 D->C->B->A (先深刻繼承樹左側,再返回,開始找右側。當把右側的class C pass掉以後,繼承的順序有變動爲D->C->B->A;

舉例以下:

 1 """新式類"""
 2 class A(object):
 3     def __init__(self):
 4         self.n = "A"
 5 
 6 class B(A):
 7    pass
 8 
 9 class C(A):
10     def __init__(self):
11         self.n = "C"
12 
13 class D(B,C):
14     pass
15 
16 d = D()
17 print d.n
18 
19 
20 """經典類"""
21 class A1:
22     def __init__(self):
23         self.n = "A1"
24 class B1(A1):
25      pass
26 class C1(A1):
27     def __init__(self):
28         self.n = "C1"
29 
30 class D1(B1,C1):
31     pass
32 
33 d1 = D1()
34 print d1.n
35 
36 輸出:
37 C
38 A1
python2中執行

 

三、類的多態實例 

   多態性(polymorphisn)是容許你將父對象設置成爲和一個或更多的他的子對象相等的技術,賦值以後,父對象就能夠根據當前賦值給它的子對象的特性以不一樣的方式運做。簡單的說,就是一句話:容許將子類類型的指針賦值給父類類型的指針。

   多態的做用是什麼呢?封裝能夠隱藏實現細節,使得代碼模塊化;繼承能夠擴展已存在的代碼模塊(類);它們的目的都是爲了——代碼重用。而多態則是爲了實現另外一個目的——接口重用!多態的做用,就是爲了類在繼承和派生的時候,保證使用「家譜」中任一類的實例的某一屬性時的正確調用。

  舉例:

 1 # _*_coding:utf-8_*_
 2 
 3 class Animal(object):
 4     def __init__(self, name):  # Constructor of the class
 5         self.name = name
 6 
 7     def talk(self):  # Abstract method, defined by convention only
 8         raise NotImplementedError("Subclass must implement abstract method")
 9 
10 
11 class Cat(Animal):
12     def talk(self):
13         print('%s: 喵喵喵!' % self.name)
14 
15 
16 class Dog(Animal):
17     def talk(self):
18         print('%s: 汪!汪!汪!' % self.name)
19 
20 
21 def func(obj):  # 一個接口,多種形態
22     obj.talk()
23 
24 
25 c1 = Cat('小晴')
26 d1 = Dog('李磊')
27 
28 func(c1)
29 func(d1)
30 輸出
31 小晴: 喵喵喵!
32 小磊: 汪!汪!汪!
多態舉例

 

做業:選課系統

角色:學校、學員、課程、講師
要求:
1. 建立北京、上海 2 所學校
2. 建立linux , python , go 3個課程 , linux\py 在北京開, go 在上海開
3. 課程包含,週期,價格,經過學校建立課程 
4. 經過學校建立班級, 班級關聯課程、講師
5. 建立學員時,選擇學校,關聯班級
5. 建立講師角色時要關聯學校, 
6. 提供兩個角色接口
  6.1 學員視圖, 能夠註冊, 交學費, 選擇班級,
  6.2 講師視圖, 講師可管理本身的班級, 上課時選擇班級, 查看班級學員列表 , 修改所管理的學員的成績 
  6.3 管理視圖,建立講師, 建立班級,建立課程 

7. 上面的操做產生的數據都經過pickle序列化保存到文件裏

相關文章
相關標籤/搜索