###### 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 繼承==
**父類別,子類別**


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()
```