Abstract modifier for C#
Tags: csharp
Published: 2022-09-12 04:33:34

使用 `abstract` 修飾詞的項目代表它具有不完整的實作，`abstract` 修飾詞可以與類別、 屬性、方法、索引子和事件搭配使用，例如標記為 `abstract` 的類別表示該類別作為其他類別的父類別，它自己不提供實作，而是由非抽象的子類別來實作

```csharp
abstract class Shape
{
	public abstract int GetArea();
}

class Square : Shape
{
	private int side;
	
	public Square(int side)
	{
		this.side = side;
	}

	public override int GetArea() => side * side;
}
```

繼承抽象類別的子類別必須包含所有抽象類別的成員實作，例如方法、存取子等等，子類別提供實作時使用 `override` 修飾詞來覆寫具有抽象修飾詞的項目。以下為例，S 繼承 F 類別卻未提供 `override` 修飾詞直接實作 Foo 方法

```csharp
abstract class F
{
	protected abstract void Foo();
}

class S : F
{
	protected void Foo() { }
}
```

此時編譯器會回報出必需實作 F 類別的 Foo 方法

![pic-014](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k7zfmvjoeu0ec6tjf0qi.png)

`abstract` 與 `sealed` 修飾詞的意義相反，抽象必須被繼承以實作，密封則是防止被繼承，故兩者不能同時使用；也不可將類別同時定義成靜態和抽象，兩者只能擇一

![pic-011](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q7i7sd8vwrejobbpi3lr.png)

不可在抽象方法中使用 `virtual` 修飾詞，否則編譯器會回報錯誤

![pic-012](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x2t0ou62c9w6ruxx3ord.png)

也不可在抽象方法中使用 `static` 修飾詞，編譯器會回報方法不可宣告為抽象

![pic-013](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wgp6ei6ztqr4er7zkmn.png)

在抽象類別中才可宣告抽象方法或屬性，但抽象類別中可以宣告非抽象的方法或屬性，如果在非抽象類別中定義抽象方法，編譯器會回報錯誤

![pic-010](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eronbk842d69uxkpf5a0.png)

當抽象類別繼承介面時，必須提供所有介面的實作，實作介面時可將方法定義為抽象或非抽象

```csharp
// 將實作介面方法定義為抽象，子類別繼承時依然須實作方法
interface IShape
{
	int GetArea();
}

abstract class Shape : IShape
{
	public abstract int GetArea();
}

class Square : Shape
{
	private int side;
	
	public Square(int side)
	{
		this.side = side;
	}

	public override int GetArea() => side * side;
}

// 或者將實作介面方法定義為非抽象，直接在抽象類別中實作方法
interface IShape
{
	int GetArea();
}

abstract class Shape : IShape
{
	protected int side = 10;
	
	public int GetArea() => side * side;
}

class Square : Shape
{
	public Square(int side)
	{
		this.side = side;
	}
}
```

嘗試使用抽象類別、屬性和方法，並在子類別提供實作

```csharp
/// <summary>
/// abstract class
/// </summary>
abstract class Shape
{
	protected int x = 10;
	protected int y = 10;

	// abstract properties
	public abstract int X { get; }
	public abstract int Y { get; }

	// abstract method
	public abstract int GetArea();
}

class Square : Shape
{
	public Square() { }
	public Square(int x, int y)
	{
		this.x = x;
		this.y = y;
	}

	// override properties
	public override int X => x + 10;
	public override int Y => y + 10;

	// override method
	public override int GetArea() => X * Y;
}
```

還有關於抽象類別很重要的一點，抽象類別不可被實體化，因為它必須被子類別繼承，再由子類別實體化後提供實作，故當嘗試將抽象類別實體化時，編譯器會會引發錯誤

![pic-009](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2fmgkdorvxazm655x53a.png)

### Reference
[abstract](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/abstract)

---

Thanks for reading the article :tulip: :sunflower: :blossom:

If you like it, please don't hesitate to click heart button :heart:
or follow my [GitHub](https://github.com/FakeStandard) :star:
or buy me a coffee :arrow_down: I'd appreciate it.

[![Buy-me-a-coffee][1]][2]

[1]: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h077sxd0vx1hix4t7lw8.png
[2]: https://www.buymeacoffee.com/FakeStandard