###### tags: `C#`
# 抽象子類別
## 說明
如果一個繼承抽象類別的衍生類別,本身又包含了抽象成員,則這個類別還是必須以 **abstract** 關鍵字進行修飾,它本身依然是一個不折不扣的抽象類別,也因此無法被用來建立實體物件。

類別 A 為一抽象類別,而類別 B 雖然繼承了類別 A ,但是由於其中另外定義了一個抽象成員`bMethod`,因此這個類別依然是一個抽象類別,類別 C 繼承了類別 B ,覆寫其中的抽象成員`bMethod`,成為一個實體類別,這三個類別當中,只有類別 C 可以用來建立實體物件。
## 範例
### 建立抽象類別
`TemplateClass`只定義了兩個抽象的方法成員,`Length`與`Area`
```csharp=
abstract class TemplateClass
{
public double len = 0;
public TemplateClass(string shape, double r)
{
this.TheShape(shape);
this.len = r;
}
private void TheShape(string shape)
{
Console.WriteLine("目前測量的形狀為{0} ", shape);
}
//抽象方法 Length、Area
abstract protected void Length(double len);
abstract protected void Area(double len);
}
```
### 繼承抽象類別
`Square`實作`TemplateClass`其抽象成員,同時又定義了一個抽象方法`Volume`,因此這個類別同樣為抽象類別
```csharp=
abstract class Square : TemplateClass
{
public Square(string shape, double len) : base(shape, len)
{ }
//實作正方形周長計算方法
protected override void Length(double len)
{
double squareLength;
squareLength = 4 * len;
Console.WriteLine("邊長為{0} 的正方形周長= {1} ", len, squareLength);
}
//實作正方形面積計算方法
protected override void Area(double len)
{
double area;
area = Math.Pow(len, 2);
Console.WriteLine
("邊長為{0} 的正方形面積= {1} ", len, area);
}
public void GetResult()
{
Length(len);
Area(len);
Volume(len);
}
//抽象方法 Volume
abstract protected void Volume(double len);
}
```
### 繼承抽象子類別
1. `Square2`繼承`Square`,並且實作其中的`Volume`成員,由於它本身並沒有進一步定義自已的抽象類別,因此為實體類別。
```csharp=
class Square2 : Square
{
public Square2(string shape, double len) : base(shape, len)
{ }
//實作正方形體積計算方法
protected override void Volume(double len)
{
double volume;
volume = Math.Pow(len, 3);
Console.WriteLine("邊長為{0} 的立方體體積= {1} ", len, volume);
}
}
```
2. 執行正方形周長、面積以及體積的計算方法
```csharp=
class Program
{
static void Main(string[] args)
{
const double len = 10;
//建立 Square 的實體物件
Square2 square = new Square2("正方形", len);
square.GetResult();
Console.ReadLine();
}
}
```
3. 執行結果
```htmlembedded=
目前測量的形狀為正方形
邊長為10 的正方形周長= 40
邊長為10 的正方形面積= 100
邊長為10 的立方體體積= 1000
```
> 參考資料 [抽象子類別](http://www.kangting.tw/2018/11/blog-post_26.html)