###### tags: `Object`,`OOP`,`Inheritance`,`Miltiple Inheritance` # Object 物件導向 & 繼承 ==Object Oriented Programming== ==物件導向Object== >現實生活中,每件事物都是物件 -實質性(眼睛看的到) -概念性(關係,師生,同儕,隨時可以轉換) >物件 -屬性Property -方法Method EX: Class Diagram | 物件名稱 | 汽車 | 狀態 |學生/員工| | ----- | --- | ---- | --- | | 屬性| 品牌、顏色 |靜態(不常變更)|工號(int)、姓名(str)| | 方法| 前、左、右、退 |動態(常更改)|輪班、領薪水| * 封裝Encapsulatio * Black Box * Data C#(強型別) ```csharp! class Employee { //利用公開方法存取私有屬性 private int id; //Id改成私有後,主程式emp.Id就沒有了(就沒有屬性了) public int Id { get { return id; } //取的動作 set { //存的動作 if (value < 0) { throw new ArgumentException("Illegal ID"); } id = value; } } public string Name; } class Program { static void Main() { try { Employee emp = new Employee(); emp.Id = -1; Console.WriteLine(emp.Id); } catch (Exception ex) { Console.WriteLine(ex); } } } ``` #UML:Unified Modeling Language Python (弱型別) ```python= class Employee: id = 0 name = '' degree = 10 #職等 > 10 領 10_0000 #職等 <= 10 領 3_0000 def salary(self): if self.degree >10: return 10_0000 else: return 3_0000 #Data Class #class Employee: # pass emp = Employee() emp.id = 1 emp.name = 'Mary' print(emp.id,emp.name) #print(emp.__dict__)#dictionary {'id': 1, 'name': 'Mary'} emp.degree = 10 print(emp.salary()) ``` C# (強型別) ```csharp! class Employee { public int Id; public string Name; } class Program { static void Main() { Employee emp = new Employee(); emp.Id = 1; emp.Name = "Mary"; Console.WriteLine(emp.Id); Console.WriteLine(emp.Name); } } ``` ```csharp! class Employee { //利用公開方法存取私有屬性 private int id; //Id改成私有後,主程式emp.Id就沒有了(就沒有屬性了) public int Id { get { return id; } //取的動作 set { //存的動作 if (value < 0) { throw new ArgumentException("Illegal ID"); } id = value; } } public string Name; } class Program { static void Main() { List<int> L = new(); L.Add(1); L.Add(2); L.Add(3); foreach (var x in L) { Console.WriteLine(x); } } } ``` python ```python! #Encapsulation 封裝(利用公開方法存取私有屬性) class Employee: def __init__(self): self.__id = 0 #同C#裡面 private int id;概念 self.__name = "" # ============================================================================= # def get_id(self): #取的動作 # return self.__id # # def set_id(self,value): #存的動作 # if value < 0: #防呆機制 # raise ValueError("Illegal ID") #raise ValueError內建語法跳出錯誤訊息 # self.__id = value # # # #寫法2 # id = property(fget=get_id,fset=set_id) # ============================================================================= #寫法3 @property def id(self): return self.__id @id.setter def id(self,value): if value < 0: raise ValueError("Illegal ID") self.__id = value emp = Employee() #寫法1 #emp.set_id(1) #emp.set_id(-1) #print(emp.get_id()) #寫法2(搭配寫法3的property) emp.id = 1 print(emp.id) ``` | 業務 | 計時制員工 | | | ----- | --- | ---- | | id / name| id / name | | | 方法| 前、左、右、退 |動態(常更改)| DRY (Don't Repeat Yourself) ==Inheritance 繼承== **父類別,子類別** ![](https://hackmd.io/_uploads/BJ-3YQiV2.jpg) ![](https://hackmd.io/_uploads/r1BW6QsV2.jpg) C# ```csharp! class Employee { public int Id { get; set; } public string Name { get; set; } } class Sales : Employee //冒號在C#代表繼承的關係,父類別有的屬性子類別就會有 { public int Quota { get; set; } } class Program { static void Main() { Sales sales = new Sales(); sales. //可以觀察.後面精靈會出現的屬性 } } ``` python ```python! #Inheritance class Employee: def __init__(self): self.__id = 0 #同C#裡面 private int id;概念 self.__name = "" @property def id(self): return self.__id @id.setter def id(self,value): if value < 0: raise ValueError("Illegal ID") self.__id = value @property def name(self): return self.__name @name.setter def name(self, value): if len(value) < 1 or len(value) > 50: raise ValueError("Illegal name") self.__name = value class Sales(Employee): #python繼承是用小括號包住 def __init__(self): #宣告私有的屬性(要用init) self.__quota = 0 @property def quota(self): return self.__quota @quota.setter def quota(self, value): self.__quota = value s = Sales() s.id = 1 s.name = "Alex" s.quota = 100_0000 print(s.id, s.name, s.quota) ``` ```python! #Python多重繼承 class B1: def f1(self): print('B1::f1()') class B2: def f2(self): print('B2::f2()') class C1(B1,B2): #C1這個類別繼承了B1,B2 pass #方法後面會帶一個小括號(),屬性可寫可不寫 c = C1() c.f1() c.f2() #假設不知道C1繼承了什麼類別,可用以下內建函示庫呼叫 print(C1.__bases__) #(<class '__main__.B1'>, <class '__main__.B2'>) ``` **繼承順序寫法,會導致結果不一樣** ```python! #繼承順序探討 class A1: def a1(self): print('ABC') class A2: def a1(self): print('CBA') #A3,A4繼承順序顛倒 class A3(A1,A2): pass class A4(A2,A1): pass p = A3() p.a1() #ABC q = A4() q.a1() #CBA ``` ```python! #探討父類別與子類別都有相同方法,若想取用自己的方法或是父類別的方法,如何操作 #探討self這個保留字 #探討super(),隱含使用父類別的方法或屬性 class D1: def d1(self): print('1234') class D2(D1): def d1(self): print('4321') def d2(self): self.d1() #4321 #super().d1() #1234 d = D2() d.d2() ```