1. 程式人生 > 其它 >面向物件程式設計,類和物件

面向物件程式設計,類和物件

面向物件程式設計

什麼是面向物件程式設計

  面向物件程式設計(OOP)就是建立“物件”。物件是一組相互關聯的變數和函式。這些變數通常稱為物件的屬性,函式
稱為物件的行為。這些物件為程式提供了一個更好、更清晰的結構。
  例如,汽車可以是一個物件。如果我們把汽車當作一個物件,那麼它的屬性就是——顏色、型號、價格、品牌等
等,它的行為/函式是加速、減速、換擋。
  另一個例子——如果我們把狗當作一個物件,那麼它的屬性就是——它的顏色、品種、名字、體重等,而它的行為/函式是行走、吠叫、玩耍等。
  面向物件程式設計(Object Oriented Programming-OOP) 是一種解決軟體複用的設計和程式設計方法。 這種方法把軟體
系統中相近相似的操作邏輯和操作 應用資料、狀態,以類的型式描述出來,以物件例項的形式在軟體系統中複用,以
達到提高軟體開發效率的作用。

面向過程程式設計和麵向物件程式設計的區別

面向過程程式設計

  面向過程程式設計(POP)的重點在於過程二字。
  面向過程比較好理解,就是按照人們通常的思維方式,在做一件事情的時候,將這件事情劃分為多個步
驟,一步一步來做。
  面向過程程式設計,就是在進行一個專案時,將這個專案分為多個小的步驟,一個步驟就是一個過程,將這些過
程全部組織起來,就形成了完整的專案。
  (C 語言是典型的面向過程程式語言)
  比如,我們可以將我要去上海這件事情分為以下四個步驟:
  1.網上買票
  2.去高鐵站
  3.坐高鐵去上海
  4.到達上海
  這裡的每個步驟相當於一個過程,我們將這些過程封裝成函式,然後,從前到後將這些函式組織起來,就完成了我要去上海這件事情。

面向物件程式設計

  面向物件程式設計(OOP)的重點在與物件二字,主要的程式設計思想是圍繞物件展開。
  在思考一個專案的時候,將專案中的重要點/關鍵點都設計成一個個的類,每個類承擔著不同的工作,不同
的功能被歸納到不同的類中。然後,由類產生出物件,這些物件之間的相互作用,最終組成了一個完整的專案。
  面向物件程式設計中的兩個非常重要概念是類與物件,類也是程式碼複用的一種機制。(程式碼複用機制:可重複使
用,就像南孚電池廣告裡說的玩具車用過遙控器還沒能接著用)

面嚮物件語言

  Java 語言是完全的面向物件程式語言,因為所有的步驟都在類中進行。

  C++ 語言是半面向物件程式語言,它被稱為帶類的 C,即支援面向過程程式設計,又支援面向物件程式設計。

  Python 語言是一門指令碼語言,以簡單優雅為設計理念,即可以面向過程程式設計,也可以面向物件程式設計,但不
像C++ 語言那樣有太多的複雜枯燥的概念,Python 語言更注重實用性。

面向物件程式設計三大特徵

  封裝,繼承和多型是面向物件的三大特徵,這三種特徵都是面向物件程式語言自身提供的機制,可以讓我們
更方便的進行面向物件程式設計:
  封裝:讓使用者可以訪問需要的方法,禁止訪問不必要的方法,遮蔽了類內部的複雜性。
  繼承:使得子類可以繼承父類的程式碼,也是一種程式碼複用手段,增強了類與類之間的邏輯結果關係。同時,
繼承也是多型的必要條件。
  多型:一個事物(物件)可以表現多種形態,多型是面向物件程式設計中,一個非常強大的特性。

類和物件

什麼是類

  這個問題的直接答案是:類是物件的集合。與原始資料結構不同,類是使用者定義的資料結構。它們使程式碼更
易於管理。
  簡單來說就是某一類事物,它們具有相同的屬性和行為或者說是方法,在程式碼中我們將這些行為或者方法定
義成函式。
  類是抽象的。
  例如,我們在說狗時,在沒有特指是什麼品種的狗,或者沒有具體哪一隻狗的時候,這個狗就是一個大類,包含了所有的狗,這時狗就是一個類,是抽象的並沒有具體到哪隻,只是指代狗這一類事物。

什麼是物件

  物件的話就是對類的實現,物件是具體的,已剛才狗為例,狗是 一個大類,是抽象的,當我們說這是一條
顏色是黑色,長尾巴,會‘汪汪’叫的小狗時,這個小狗就是物件,它是具體存在的是一個實體。
  這一個過程我們可以看成將一個抽象的類轉化成了一個具體的有屬性和行為或者說方法的物件,在程式碼中
我們稱這個過程為例項化。

類:抽象的,是一張“手機設計圖”。
物件:具體的,是一個“真正的手機例項”。

類的建立

  在python中一個類的建立使用class關鍵字實現其基本語法格式如下:
  class 類名:
    多個(≥0)類屬性...
    多個(≥0)類方法...
  給類起好名字之後,其後要跟有冒號(:),表示告訴 Python 直譯器,下面要開始設計類的內部功能
了,也就是編寫類屬性和類方法。
  例:
    class Student():
      school = '家裡蹲大學'
      def eat(self):
          print('吃飯')
  事實上,我們完全可以建立一個沒有任何類屬性和類方法的類,換句話說,Python 允許建立空類:
  class Empty:
    pass

新式類和舊式類

  # class Hero:  # 經典類(舊式類)定義形式
  # class Hero():

  class Hero(object):  # 新式類定義形式
      def info(self):
          print("英雄各有見,何必問出處。")
  '''
    ①定義類時有2種形式:新式類和經典類,上面程式碼中的Hero為新式類,前兩行註釋部分則為經典類;
    ②object 是Python 裡所有類的最頂級父類;
    ③類名 的命名規則按照"大駝峰命名法";
    ④info 是一個例項方法,第一個引數一般是self,表示例項物件本身,當然了可以將self換為其它的名字,其作用是一個變數這個變數指向了例項物件
  '''

物件例項化

例項化物件

  例項化基本語法:
    物件名 = 類名()
  當類中構造方法除了self還有別的引數時:
    物件名 = 類名(引數1,引數2,引數3...)

  例:
    class Cat:
    """定義了一個Cat類"""

      #方法
      def eat(self):
          print("貓在吃魚....")
      def drink(self):
          print("貓正在喝kele.....")
      def introduce(self):
          print("%s的年齡是:%d"%(self.name, self.age))

    #建立一個物件
    tom = Cat()

__init__類構造方法

物件既然有例項方法,是否也可以有自己的屬性?
  新增和獲取物件的屬性
  class Hero(object):
      """定義了一個英雄類,可以移動和攻擊"""
      def move(self):
          """例項方法"""
          print("正在前往事發地點...")

      def attack(self):
          """例項方法"""
          print("發出了一招強力的普通攻擊...")

  # 例項化了一個英雄物件 泰達米爾
  taidamier = Hero()

  # 給物件新增屬性,以及對應的屬性值
  taidamier.name = "泰達米爾"  # 姓名
  taidamier.hp = 2600  # 生命值
  taidamier.atk = 450  # 攻擊力
  taidamier.armor = 200  # 護甲值

  # 通過.成員選擇運算子,獲取物件的屬性值
  print("英雄 %s 的生命值 :%d" % (taidamier.name, taidamier.hp))
  print("英雄 %s 的攻擊力 :%d" % (taidamier.name, taidamier.atk))
  print("英雄 %s 的護甲值 :%d" % (taidamier.name, taidamier.armor))

  # 通過.成員選擇運算子,獲取物件的例項方法
  taidamier.move()
  taidamier.attack()
  
  結果為:
    英雄 泰達米爾 的生命值 :2600
    英雄 泰達米爾 的攻擊力 :450
    英雄 泰達米爾 的護甲值 :200
    正在前往事發地點...
    發出了一招強力的普通攻擊...
物件建立並新增屬性後,能否在類的例項方法裡獲取這些屬性呢?如果可以的話,應該通過什麼方式?
  在方法內通過self獲取物件屬性
  class Hero(object):
      """定義了一個英雄類,可以移動和攻擊"""
      def move(self):
          """例項方法"""
          print("正在前往事發地點...")

      def attack(self):
          """例項方法"""
          print("發出了一招強力的普通攻擊...")

      def info(self):
          """在類的例項方法中,通過self獲取該物件的屬性"""
          print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
          print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
          print("英雄 %s 的護甲值 :%d" % (self.name, self.armor))


  # 例項化了一個英雄物件 泰達米爾
  taidamier = Hero()

  # 給物件新增屬性,以及對應的屬性值
  taidamier.name = "泰達米爾"  # 姓名
  taidamier.hp = 2600  # 生命值
  taidamier.atk = 450  # 攻擊力
  taidamier.armor = 200  # 護甲值

  # 通過.成員選擇運算子,獲取物件的例項方法
  taidamier.info()  # 只需要呼叫例項方法info(),即可獲取英雄的屬性
  taidamier.move()
  taidamier.attack()
  
  執行結果:
    英雄 泰達米爾 的生命值 :2600
    英雄 泰達米爾 的攻擊力 :450
    英雄 泰達米爾 的護甲值 :200
    正在前往事發地點...
    發出了一招強力的普通攻擊...
init()方法
  建立物件後再去新增屬性有點不合適,有沒有簡單的辦法,可以在建立物件的時候,就已經擁有這些屬性?

  class Hero(object):
      """定義了一個英雄類,可以移動和攻擊"""
      # Python 的類裡提供的,兩個下劃線開始,兩個下劃線結束的方法,就是魔法方法,__init__()就是一個魔法方法,通常用來做屬性初始化 或 賦值 操作。
      # 如果類面沒有寫__init__方法,Python會自動建立,但是不執行任何操作,
      # 如果為了能夠在完成自己想要的功能,可以自己定義__init__方法,
      # 所以一個類裡無論自己是否編寫__init__方法 一定有__init__方法。

      def __init__(self):
          """ 方法,用來做變數初始化 或 賦值 操作,在類例項化物件的時候,會被自動呼叫"""
          self.name = "泰達米爾" # 姓名
          self.hp = 2600 # 生命值
          self.atk = 450  # 攻擊力
          self.armor = 200  # 護甲值

      def info(self):
          """在類的例項方法中,通過self獲取該物件的屬性"""
          print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
          print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
          print("英雄 %s 的護甲值 :%d" % (self.name, self.armor))

      def move(self):
          """例項方法"""
          print("正在前往事發地點...")

      def attack(self):
          """例項方法"""
          print("發出了一招強力的普通攻擊...")


  # 例項化了一個英雄物件,並自動呼叫__init__()方法
  taidamier = Hero()

  # 通過.成員選擇運算子,獲取物件的例項方法
  taidamier.info() # 只需要呼叫例項方法info(),即可獲取英雄的屬性
  taidamier.move()
  taidamier.attack()

  執行結果:
    英雄 泰達米爾 的生命值 :2600
    英雄 泰達米爾 的攻擊力 :450
    英雄 泰達米爾 的護甲值 :200
    正在前往事發地點...
    發出了一招強力的普通攻擊...
有參__init__()
  class Hero(object):
      """定義了一個英雄類,可以移動和攻擊"""

      def __init__(self, name, skill, hp, atk, armor):
          """ __init__() 方法,用來做變數初始化 或 賦值 操作"""
          # 英雄名
          self.name = name
          # 技能
          self.skill = skill
          # 生命值:
          self.hp = hp
          # 攻擊力
          self.atk = atk
          # 護甲值
          self.armor = armor

      def move(self):
          """例項方法"""
          print("%s 正在前往事發地點..." % self.name)

      def attack(self):
          """例項方法"""
          print("發出了一招強力的%s..." % self.skill)

      def info(self):
          print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
          print("英雄 %s 的攻擊力 :%d" % (self.name, self.atk))
          print("英雄 %s 的護甲值 :%d" % (self.name, self.armor))


  # 例項化英雄物件時,引數會傳遞到物件的__init__()方法裡
  taidamier = Hero("泰達米爾", "旋風斬", 2600, 450, 200)
  gailun = Hero("蓋倫", "大寶劍", 4200, 260, 400)

  # 直接輸出物件即為地址
  print(gailun)
  # <__main__.Hero object at 0x0318B100>
  print(taidamier)
  # <__main__.Hero object at 0x0318B0D0>

  # 不同物件的屬性值的單獨儲存
  print(id(taidamier.name))
  print(id(gailun.name))

  # 同一個類的不同物件,例項方法共享
  print(id(taidamier.move()))
  # 泰達米爾 正在前往事發地點...
  # 2045877480
  print(id(gailun.move()))
  # 蓋倫 正在前往事發地點...
  # 2045877480
  因為我之前學習的是java,當我看到這個的時候我就會覺得很熟悉,這不就是Java中的建構函式,在java
中有2種建構函式有參和無參。那麼我就可以將這個理解為java中的建構函式。

  簡單的介紹一下什麼是建構函式:
    建立一個物件時,通常最需要立即做的工作是初始化物件,如對資料成員賦初值
    建構函式就是用來在創造物件時初始化物件,為物件資料成員賦初始值
    類的資料成員是不能在類的定義時初始化的
  使用方法:
     class 類名:
         #初始化函式,用來完成一些預設的設定
         def __init__():
            pass
   __init__()方法,在建立一個物件時預設被呼叫,不需要手動呼叫
   __init__(self)中,預設有1個引數名字為self,如果在建立物件時傳遞了2個實參,那__init__(self)
中除了self作為第一個形參外還需要2個形參,例如__init__(self,x,y)
   __init__(self)中的self引數,不需要開發者傳遞,python直譯器會自動把當前的物件引用傳遞進去
  例:
    class Cat:
    """定義了一個Cat類"""
      #初始化物件
      def __init__(self, new_name, new_age):
          self.name = new_name
          self.age = new_age

物件的屬性取值和方法呼叫

  屬性取值基本語法:
    物件名.屬性名
  方法呼叫基本語法:
    物件名.函式名(如果需要引數則傳入引數)
  例:
    class Cat:
        '''定義了一個Cat類'''

        # 初始化物件
        def __init__(self, new_name, new_age):
            self.name = new_name
            self.age = new_age

        # 方法
        def eat(self):
            print("貓在吃魚....")

        def drink(self):
            print("貓正在喝kele.....")

        def introduce(self):
            print("%s的年齡是:%d" % (self.name, self.age))

    # 建立一個物件
    tom = Cat("湯姆", 40)
    # 獲取tom的new_name屬性
    print(tom.name)
    # 獲取tom的new_age屬性
    print(tom.age)
    # 呼叫方法
    tom.eat()
    tom.drink()
    tom.introduce()
    執行結果:
    湯姆
    40
    貓在吃魚....
    貓正在喝kele.....
    湯姆的年齡是:40