iT邦幫忙

2023 iThome 鐵人賽

DAY 9
1

學習原因:

在 Automation Test 中 Page Object Model (POM) 就是應用 OOP 設計出來的,所以需要先理解概念,後續做測試專案的時候才能運用自如。應用 OOP 設計再搭配之前 Module 和 Package 的概念,將會對你的專案架構設計產生很大的幫助。

學習目標:

  • 認識 OOP 的 3 個重要概念
    • 封裝 (Encapsulation)
    • 繼承 (Inheritance )
    • 多型 (Polymorphism)
  • 了解 OOP 設計的優點

Object Orientation Programming (OOP)

說到物件導向,必須要知道的三個概念:

  1. 封裝 Encapsulation

    上一篇文章講述的內容,把 attribute 和 Method 組成一個 Class,其實就是封裝的概念。

    舉個應用例子,當需要處理多位學生的個人資料以及上課記錄等資料,而每位學生都有獨立的資料需要處理,因此把 學生的資料 和 處理資料的 method 封裝成一個 Class 如下:

    class Student:
    	student_id = ""
    	student_name = ""
    	sex = ""
    	attendance = 0
    
    	def attend_lesson(self)
    		self.attendance += 1
    

    透過這樣的設計,可以為每個學生建立一個 Object,而個別都擁有處理自己資料的方法。

  2. 繼承 Inheritance

    從既有的 Class (父類別 Parent Class) 定義出新的 子類別 (Child Class),子類別可以繼承父類別的屬性和方法,亦可以加入自己的屬性和方法,甚至重新定義從父類別繼承的方法,但不影響父類別的方法。

    如下的一個例子,寵物有很多種,但牠們都有進食技能。然而狗還可以抓貓,而貓則可以抓老鼠。這時候把他們都該有的屬性和方法寫進父類別,個別特有的方法寫在子類別。

    class Pet:
    	# 每隻寵物,不管什麼類型,都有名字,因此初始化的動作在父類別進行
    	def __init__(self, name):
    		self.name = name
    
    	# 每隻寵物,不管什麼類型,都會吃東西
    	def eat(self):
    		print(f"{self.name} can eat")
    
    # 定義寵物種類為狗
    class Dog(Pet):
    
    	# 狗類寵物有抓貓技能
    	def catch_cat(self):
    		print(f"{self.name} can catch cat")
    
    # 定義寵物種類為貓
    class Cat(Pet):
    
    	# 貓類寵物有抓鼠技能
    	def catch_mouse(self):
    		print(f"{self.name} can catch mouse")
    
    snoopy = Dog("Snoopy")
    snoopy.eat() 
    snoopy.catch_cat()
    
    garfield = Cat("Garfield")
    garfield.eat()
    garfield.catch_mouse()
    

    Output:

    Snoopy can eat
    Snoopy can catch cat
    Garfield can eat
    Garfield can catch mouse
    

    繼承的好處是可以提高方法的重用性,只需要在父類別撰寫一次,就可以被子類別重複使用。

    除了這種一般的繼承,還有多重繼承多層繼承

    • 多重繼承 : 同時繼承多過一個父類別,就像是同是繼承父親的基因,也繼承母親的基因。

      https://ithelp.ithome.com.tw/upload/images/20230913/20162038tyOZ6AIEj8.png

      class Animal:
          def __init__(self, name):
              self.name = name
      
          def speak(self):
              print(f"{self.name} says Hello World!")
      
      class Flyable:
          def fly(self):
              print(f"I can fly.")
      
      class Bird(Animal, Flyable):
          def sing(self):
              print(f"{self.name} is singing.")
      
      sparrow = Bird("Sparrow")
      sparrow.speak()
      sparrow.fly()
      sparrow.sing()
      

      Output:

      Sparrow says Hello World!
      I can fly.
      Sparrow is singing.
      
    • 多層繼承 : 子類別有父類別,父類別也有父類別,祖父的概念。子類別同樣可以得到祖父層的屬性與方法。
      https://ithelp.ithome.com.tw/upload/images/20230913/20162038J8Y7YSpbSu.png

      class Animal:
          def __init__(self, name):
              self.name = name
      
          def eat(self):
              print(f"{self.name} like bone")
      
      class Dog(Animal):
          def speak(self):
              print(f"{self.name}: Woof! Woof!")
      
      class GoldenRetriever(Dog):
          def fetch(self):
              print(f"{self.name} is fetching a ball.")
      
      dog = GoldenRetriever("Buddy")
      dog.eat()
      dog.speak()
      dog.fetch()
      

      Output:

      Buddy like bone
      Buddy: Woof! Woof!
      Buddy is fetching a ball.
      
  3. 多型 Polymorphism

    是指子類別繼承父類別的方法,但可能會有不一樣的處理方式。承上的例子,這些寵物都會發聲,但發出的聲音就不一樣了。

    class Pet:
        def make_sound(self):
            print("Hello")
    
    class Dog(Pet):
        def make_sound(self):
            print("Woof!")
    
    class Cat(Pet):
        def make_sound(self):
            print("Meow!")
    
    snoopy = Dog()
    garfield = Cat()
    
    # 呼叫通用方法,實際執行的方法取決於物件的類型
    snoopy.make_sound()  # 輸出: Woof!
    garfield.make_sound()  # 輸出: Meow!
    

    順帶一題 Python 有內建的套件 abc (abstract based class) ,有一個裝飾器 @abstractmethod,用來標記 class 中的 method 為抽象方法,用處是父親沒有實際定義方法的內容,但其子類別必須定義該方法的實作內容,否則會噴錯,藉此來規範子類別需要實作的內容。

    # 需 import abc 套件
    from abc import abstractmethod, ABC
    
    # Pet 需要繼承 ABC class 才能應用 @abstractmethod
    class Pet(ABC):
    
    		# 標記為 abstractmethod,裡面沒有實作內容,會寫 pass
        @abstractmethod
        def make_sound(self):
            pass
    
    class Dog(Pet):
        def make_sound(self):
            print("Woof!")
    
    class Cat(Pet):
    		# 沒有實作 make_sound() 的內容
    		def catch_mouse(self):
    				print("I can catch mouse")
    
    snoopy = Dog()
    snoopy.make_sound()
    
    # 在 init 的時候就會因為沒有實作 make_sound() 而噴錯
    garfield = Cat()
    

    Output:

    Woof!
    ...
    ...
    TypeError: Can't instantiate abstract class Cat with abstract method make_sound
    

OOP 程式設計的好處

  1. 作整理收納,隱藏程式細節,只提供清楚的應用方法,讓主程式變得簡潔,大幅提高可讀性
  2. 封裝的 Method,可被大量重複使用,只需一次的撰寫或偵錯,提高可重用性,以及可維護性
  3. 同時亦可具備差異性,讓程式碼易於擴展

以上是關於 OOP 的介紹,需要理解這些概念,之後才會更好理解 Page Object Model 的設計,對於整個專案架構設計都很有幫助。


上一篇
Day 08: Python 的 Class 和 Object
下一篇
Day 10: SQL Database - SQL Selection
系列文
從 0 開始培育成為自動化測試工程師的學習指南30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言