#再見物件導向
##之勇者鬥惡龍
2017/12/14 阮韞澂
##Out Lines
- 繼承
- 繼承修飾詞
- 多型
- 泛型
- 練習
##繼承--劍的設計圖
- 劍 (雙刃,可以揮砍)
- 大劍 : 劍 (雙刃,可以揮砍,很重)
- 短劍 : 劍 (雙刃,可以揮砍,很輕)
- 紅色的大劍 : 大劍 (雙刃,可以揮砍,很重,很潮)
##繼承
- Inheritance
- 在一個類別的基礎上建構另一個類別
##繼承
- B類別繼承A類別
- 父類別A,子類別B
- B類別為A類別的擴充改裝
- A有的B都有
##繼承
```
class B : A
{
//類別B的成員內容
}
```
##繼承
```
class A
{
public int I = 5;
}
class B : A
{}
static void Main(string[] args)
{
A a = new A();
Console.WriteLine(a.I); //5
B b = new B();
Console.WriteLine(b.I); //5
```
##繼承
```
class A
{
public void foo() { Console.WriteLine("foo!"); }
}
class B : A
{ }
static void Main(string[] args)
{
A a = new A();
a.foo(); //foo!
B b = new B();
b.foo(); //foo!
```
##繼承
- Every thing is Object
- 根節點
- 所有的類別都可以是Object
- Object有的所有人都有
```
Object o = new Object();
o.ToString();
o.GetType();
o.GetHashCode();
o.Equals(o);
```
##繼承修飾詞
- override
- virtual
- abstract
- new //略過
- sealed
##繼承修飾詞--override
- 覆寫的
- 用於子類別
- 重新實作父類別的成員
##繼承修飾詞--override
```
class Foo
{
private int a = 3;
private int b = 5;
public override string ToString()
{
return (a + b).ToString();
}
}
static void Main(string[] args)
{
Foo f = new Foo();
Console.WriteLine(f.ToString()); //8
```
##繼承修飾詞--virtual
- 虛擬的
- 用於父類別
- 成員在繼承的類別中可以被重新實作
- 可以正常使用
##繼承修飾詞--virtual
```
class Foo
{
public virtual int GetFoo(int i) { return i * 2; }
}
class Bar : Foo
{
public override int GetFoo(int i) { return i * 3; }
}
static void Main(string[] args)
{
Foo f = new Foo();
Console.WriteLine(f.GetFoo(5)); //10
Bar b = new Bar();
Console.WriteLine(b.GetFoo(5)); //15
```
##練習
- 建立Character類別(HP, IsAlive, GetAttack)
- 建立Player和Dragon類別繼承自Character
- 在winform建立RefreshHP()方法以更新頁面HP顯示
##繼承修飾詞--abstract
- 武器
- 一種用於攻擊的裝備
- 沒有一種武器真的叫做"武器"
##繼承修飾詞--abstract
- 抽像的,沒有實體
- 一種概念
- 用於父類別
- 用於類別本身或類別成員
##繼承修飾詞--abstract
- abstract class
- 抽像類別
- 不可被實體化
##繼承修飾詞--abstract
- abstract method, abstract property
- 抽像方法,抽像屬性
- 父類別指出結構
- 繼承的子類別必須要實作
##繼承修飾詞--abstract
```
abstract class Foo
{
protected abstract int FF { get; }
public abstract int GetFoo(int i);
}
class Bar : Foo
{
protected override int FF { get => 3; }
public override int GetFoo(int i) { return i * FF; }
}
static void Main(string[] args)
{
//抽象類別不可被實體化
//Foo f = new Foo();
Bar b = new Bar();
Console.WriteLine(b.GetFoo(5)); //15
```
##練習
- 將Character類別修改為抽象類別
- 加入抽象屬性(Name, BaseHP)
- 在Player和Dragon類別實作繼承的抽象屬性
##練習
- 建立抽象類別Weapon(Name, BaseDamage, DiceNumber, DiceSide, GetDamage())
- 建立類別LittleKnife, Sword, Excalibur繼承自Weapon
##繼承修飾詞--sealed
- 封印的
- 用於類別本身或類別成員
##繼承修飾詞--sealed
- sealed class
- 封印類別
- 此類別不可被繼承
##繼承修飾詞--sealed
- sealed method, sealed property
- 封印方法,封印屬性
- 子類別不可覆寫此成員
##繼承--base
- base關鍵字
- 代表當前物件的父類別成員
- 不能多重使用(base.base.Prop)
##繼承--base
```
public class Foo
{
protected virtual int I { get => 2; }
public virtual int GetFoo() { return 3; }
}
public class Bar : Foo
{
protected override int I { get => 5; }
public override int GetFoo() { return base.I * base.GetFoo() * I; }
}
static void Main(string[] args)
{
Bar b = new Bar();
Console.WriteLine(b.GetFoo()); //30
```
##多型
- 武器可以攻擊
- 劍.攻擊
- 大劍.攻擊
- 短劍.攻擊
- 紅色的大劍.攻擊
##多型
- Polymorphism
- 子類別的物件以父類別的功能執行,表現出的行為是子類別自身實作的行為
##多型
```
class Foo
{
public virtual string GetFoo() { return "FOO"; }
}
class Bar : Foo
{
public override string GetFoo() { return "BAR!"; }
}
static void Main(string[] args)
{
Foo f = new Foo();
Bar b = new Bar();
Foo o = new Bar();
Console.WriteLine(f.GetFoo()); //"FOO"
Console.WriteLine(b.GetFoo()); //"BAR!"
Console.WriteLine(o.GetFoo()); //"BAR!"
```
##多型
```
public class OutPut
{
public void OutPutFoo(Foo f)
{
Console.WriteLine(f.GetFoo());
}
}
static void Main(string[] args)
{
Foo f = new Foo();
Bar b = new Bar();
OutPut o = new OutPut();
o.OutPutFoo(f); //"FOO"
o.OutPutFoo(b); //"BAR!"
```
##練習
- 在Character類別建立GetAttack(Character, Weapon)方法
- 在winform建立PlayerAttack(Weapon)方法
- 在winform設定三種攻擊方式
##回家練習
- 在遊戲中加入死亡的判斷
- 建立抽象類別Armor(屬性:DefensePoint)
- 建立LeatherArmor, SteelArmor, MysteriousSteelArmor繼承自Armor
- 在Player類別加入EquipArmor屬性儲存Armor
- 改寫GetAttack方法,承受傷害時扣除Armor.DefensePoint
##泛型
- Generic
- 將型別參數化
- 可用於類別或方法
- List< T >
```
List<int> list = new List<int>();
```
##泛型方法
```
public class Foo
{
public void DoSomething<T>(T t)
{
//DoSomething
}
}
static void Main(string[] args)
{
Foo f = new Foo();
f.DoSomething<int>(123);
f.DoSomething<string>("ABC");
```
##泛型類別
```
public class Foo<T>
{
public T Prop { get; set; }
public T Bar<R1, R2>(R1 r, T t) { return default(T); }
}
static void Main(string[] args)
{
Foo<int> f1 = new Foo<int>();
f1.Prop = 123;
Foo<string> f2 = new Foo<string>();
f2.Prop = "ABC";
```