您的位置:首页 > 编程语言 > C语言/C++

interface和abstract class有何不同? (C/C++) (.NET) (C#)

2014-08-31 11:23 302 查看
Abstract

這兩個的確非常的像,主要都是為了實踐『多型』,但實際的用途並不一樣。

Introduction

interface和abstract class在語言層次的差異,我就不再贅述,本文主要是放在何時該使用interface?何時該使用abstract class?

interface用在當一個物件須和其他物件共同合作時,為了確保其他物件有我想要的method,所以定下interface要該物件遵守,在Design Pattern到處可以看到這種應用,如strategy,bridge,prototype...。

而abstract class是用在整個繼承體系的最上層,用來定義出整個繼承體系該有哪些method,子類別可以對這些method加以override,或維持和abstract class相同的功能。Design Pattern中的template method,factory method...等就是用這種手法。

或者更明白的說,我們知道在OO主要有兩種技術:繼承(Inheritance)和組合(Composition),而abstract class就是用在使用繼承技術時,而interface則是用在使用組合技術時。

使用繼承技術時,我們會將所有method由abstract class去宣告,然後由各子類別去override,若不得已某些class有自己的特殊method,則由該class自行宣告。

一旦使用組合時時,就牽涉到一個問題,你如何確保被你組合的物件有某個method呢?當你使用繼承時,因為所有的method都會被繼承,這不是問題,但組合就不一樣了,所以你必須建立一個interface,強迫要被你組合的物件,需實做這個interface,這樣當你要使用該物件時,才能確保有某個method可以呼叫。

Sample Code

以Door為例,Door是一個泛稱,適合當abstract class,定義出open()和close(),由於一般們都是水平左右開,所以可以將左右開的功能放在abstract class,今天有一個垂直上下開的門VerticalDoor,門是水平開的,明顯和abstract class不一樣,所以使用了override的方式去改寫,在此範例我們使用了『繼承』的技術。

UML





C++



1

/*

2

(C) OOMusou 2007 http://oomusou.cnblogs.com

3


4

Filename : DoorInheritance.cpp

5

Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++

6

Description : Demo how to use abstract class

7

Release : 05/07/2007 1.0

8

*/

9


10

#include <iostream>

11

#include <vector>

12

#include <algorithm>

13

#include <functional>

14


15

using namespace std;

16


17

class Door {

18

public:

19

virtual void open() const {

20

cout << "open horizontally" << endl;

21

}

22


23

virtual void close() const {

24

cout << "close horizontally" << endl;

25

}

26

};

27


28

class HorizontalDoor : public Door {

29

};

30


31

class VerticalDoor : public Door {

32

public:

33

void open() const {

34

cout << "open vertically" << endl;

35

}

36


37

void close() const {

38

cout << "close vertically" << endl;

39

}

40

};

41


42

class DoorController {

43

protected:

44

vector<Door*> _doorVec;

45


46

public:

47

void addDoor(Door& aDoor) {

48

_doorVec.push_back(&aDoor);

49

}

50


51

void openDoor() const {

52

for_each(_doorVec.begin(), _doorVec.end(), mem_fun(&Door::open));

53

}

54

};

55


56


57

int main() {

58

DoorController dc;

59

dc.addDoor(HorizontalDoor());

60

dc.addDoor(VerticalDoor());

61

dc.openDoor();

62

}

C#



1

/*

2

(C) OOMusou 2007 http://oomusou.cnblogs.com

3


4

Filename : DoorInheritance.cs

5

Compiler : Visual Studio 2005 / C# 2.0

6

Description : Demo how to use abstract class

7

Release : 05/07/2007 1.0

8

*/

9

using System;

10

using System.Collections.Generic;

11


12

class Door {

13

public virtual void open() {

14

Console.WriteLine("open horizontally");

15

}

16


17

public virtual void close() {

18

Console.WriteLine("close horizontally");

19

}

20

}

21


22

class HorizontalDoor : Door {

23

}

24


25

class VerticalDoor : Door {

26

public override void open() {

27

Console.WriteLine("open vertically");

28

}

29


30

public override void close() {

31

Console.WriteLine("close vertically");

32

}

33

}

34


35

class DoorController {

36

protected List<Door> _doorList = new List<Door>();

37


38

public void addDoor(Door aDoor) {

39

_doorList.Add(aDoor);

40

}

41


42

public void openDoor() {

43

foreach(Door iter in _doorList) {

44

iter.open();

45

}

46

}

47

}

48


49

class main {

50

public static void Main() {

51

DoorController dc = new DoorController();

52

dc.addDoor(new HorizontalDoor());

53

dc.addDoor(new VerticalDoor());

54

dc.openDoor();

55

}

56

}

執行結果




open horizontally


open vertically

假如日後需求改變,需要一個會警報的門AlarmDoor,由於廠商本身沒有生產警報器,所以勢必外包,這時他將規格定義成IAlarm interface,只要能生產出這個規格的Alarm,就可以透過『組合』的方式產生出會警報的門,在此範例我們使用『組合』技術。

UML(以下這個圖我畫錯了,_alarm應該在AlarmDoor內,感謝frank28_nfls的指正,C++與C#的code是對的)





C++



1

/*

2

(C) OOMusou 2007 http://oomusou.cnblogs.com

3


4

Filename : DoorInheritance.cpp

5

Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++

6

Description : Demo how to use interface

7

Release : 05/07/2007 1.0

8

*/

9


10

#include <iostream>

11

#include <vector>

12

#include <algorithm>

13

#include <functional>

14


15

using namespace std;

16


17

class Door {

18

public:

19

virtual void open() const {

20

cout << "open horizontally" << endl;

21

}

22


23

virtual void close() const {

24

cout << "close horizontally" << endl;

25

}

26

};

27


28

class HorizontalDoor : public Door {

29

};

30


31

class VerticalDoor : public Door {

32

public:

33

void open() const {

34

cout << "open vertically" << endl;

35

}

36


37

void close() const {

38

cout << "close vertically" << endl;

39

}

40

};

41


42

class IAlarm {

43

public:

44

virtual void alert() const = 0;

45

};

46


47

class Alarm : public IAlarm {

48

public:

49

void alert() const {

50

cout << "ring,ring,ring" << endl;

51

}

52

};

53


54

class AlarmDoor : public Door {

55

protected:

56

IAlarm* _alarm;

57


58

public:

59

AlarmDoor() {

60

_alarm = new Alarm;

61

}

62


63

~AlarmDoor() {

64

delete _alarm;

65

}

66


67

public:

68

void alert() {

69

_alarm->alert();

70

}

71

};

72


73

class DoorController {

74

protected:

75

vector<Door*> _doorVec;

76


77

public:

78

void addDoor(Door& aDoor) {

79

_doorVec.push_back(&aDoor);

80

}

81


82

void openDoor() {

83

for_each(_doorVec.begin(), _doorVec.end(), mem_fun(&Door::open));

84

}

85

};

86


87

int main() {

88

DoorController dc;

89

dc.addDoor(HorizontalDoor());

90

dc.addDoor(VerticalDoor());

91

dc.addDoor(AlarmDoor());

92

dc.openDoor();

93


94

Door& door = AlarmDoor();

95

dynamic_cast<AlarmDoor&>(door).alert();

96

}

C#

1

/*

2

(C) OOMusou 2007 http://oomusou.cnblogs.com

3


4

Filename : DoorInheritance.cs

5

Compiler : Visual Studio 2005 / C# 2.0

6

Description : Demo how to use interface

7

Release : 05/07/2007 1.0

8

*/

9


10

using System;

11

using System.Collections.Generic;

12


13

abstract class Door {

14

public virtual void open() {

15

Console.WriteLine("open horizontally");

16

}

17


18

public virtual void close() {

19

Console.WriteLine("close horizontally");

20

}

21

}

22


23

class HorizontalDoor : Door {

24

}

25


26

class VerticalDoor : Door {

27

override public void open() {

28

Console.WriteLine("open vertically");

29

}

30


31

override public void close() {

32

Console.WriteLine("close vertically");

33

}

34

}

35


36

interface IAlarm {

37

void alert();

38

}

39


40

class Alarm : IAlarm {

41

public void alert() {

42

Console.WriteLine("ring,ring,ring");

43

}

44

}

45


46

class AlarmDoor : Door {

47

private IAlarm _alarm;

48


49

public AlarmDoor() {

50

_alarm = new Alarm();

51

}

52


53

public void alert() {

54

_alarm.alert();

55

}

56

}

57


58

class DoorController {

59

protected List<Door> _doorList = new List<Door>();

60


61

public void addDoor(Door aDoor) {

62

_doorList.Add(aDoor);

63

}

64


65

public void openDoor() {

66

foreach (Door iter in _doorList) {

67

iter.open();

68

}

69

}

70

}

71


72

class main {

73

public static void Main() {

74

DoorController dc = new DoorController();

75

dc.addDoor(new HorizontalDoor());

76

dc.addDoor(new VerticalDoor());

77

dc.addDoor(new AlarmDoor());

78

dc.openDoor();

79


80

Door door = new AlarmDoor();

81

((AlarmDoor)(door)).alert();

82

}

83

}



執行結果




open horizontally


open vertically


open horizontally


ring,ring,ring

值得注意的是,我並沒有將Door()這個abstract class加上alert(),因為alert()並非所有門都有,所以不應該放在abstract class,另外abstract class也不該隨意更改,所以才會說,abstract class和interface在設計時非常重要,整個多型的技術都是靠interface和abstract class支撐,只要interface或abstract class一變,整個多型機制就瓦解了。

Conclusion

interface和abstract class的差異,重點是在用的地方完全不同,而非僅是語法上的小差異,若從語言差異的角度去看interface和abstract class,當然會搞的一頭霧水,若從OO和Design Pattern的角度去看,才能較容易分辨interface和abstract的異同。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: