第 44 講:結(jié)構(gòu)(三):結(jié)構(gòu)和繼承機(jī)制
在 C# 里,官方團(tuán)隊(duì)為了靈活使用這個(gè)編程語言,就把 C# 設(shè)計(jì)得非常靈活。C# 里的結(jié)構(gòu)雖然不能自定義繼承關(guān)系,但可以自定義實(shí)現(xiàn)接口。而因?yàn)榻Y(jié)構(gòu)是自動(dòng)從 ValueType
這個(gè)類派生起來的,因此今天我們會(huì)把結(jié)構(gòu)的繼承機(jī)制和實(shí)現(xiàn)接口的機(jī)制都給大家介紹一下。
Part 1 結(jié)構(gòu)實(shí)現(xiàn)接口的語法
和類的接口實(shí)現(xiàn)完全一樣,結(jié)構(gòu)的接口實(shí)現(xiàn),寫法完全沒有區(qū)別。只是因?yàn)榻Y(jié)構(gòu)不能自定義繼承關(guān)系,因此我們沒有類的繼承機(jī)制了,只剩下接口的實(shí)現(xiàn)列表。
舉個(gè)例子。假設(shè)我們有一個(gè)自定義的整數(shù)類型 Integer
,那么它顯然可以實(shí)現(xiàn)比如下面這樣的一些接口。
對(duì)吧,比如說這里的 ICalculatable
對(duì)應(yīng)了加減乘除模五大基本算術(shù)運(yùn)算,IFormattable
對(duì)應(yīng)了輸出一個(gè)整數(shù)數(shù)據(jù)的字符串的時(shí)候,的排版格式(比如要不要添加開頭的正負(fù)號(hào)啊,要不要三位一分節(jié)之類的),IConvertible
定義了這個(gè)類型和其他基本數(shù)據(jù)類型的轉(zhuǎn)換方法。
只需要挨個(gè)實(shí)現(xiàn)接口里的成員,就 OK 了。用法和類的接口實(shí)現(xiàn)是沒有區(qū)別的,而且也分顯式接口實(shí)現(xiàn)和隱式接口實(shí)現(xiàn)兩種,寫法都和之前講過的那樣,沒有區(qū)別。
Part 2 ValueType
是個(gè)什么幺蛾子
之前我們就簡單說過了,ValueType
是一個(gè)引用類型(用類表達(dá)出來的,而不是接口)。而這個(gè) ValueType
是沒有基類型繼承的自定義關(guān)系的,默認(rèn)是從 object
派生。那么 ValueType
里到底有一些什么成員呢?
呃,其實(shí)不必多說。你照著 object
來看就可以了。因?yàn)槭峭耆粯拥?。之前說過,object
有這些成員:
無參構(gòu)造器;
Equals
方法(virtual
修飾,可重寫);ReferenceEquals
方法(static
修飾,不可重寫);ToString
方法(virtual
修飾,可重寫);GetHashCode
方法(virtual
修飾,可重寫);operator ==
等號(hào)運(yùn)算符(可重載);operator !=
不等號(hào)運(yùn)算符(可重載)。
而 ValueType
也是這些成員。不過因?yàn)?ValueType
是 object
的一個(gè)子類型,所以標(biāo)記的不是 virtual
,而是 override
。不過,因?yàn)?ValueType
還提供給別的結(jié)構(gòu)繼承,因此本身是沒有標(biāo)記 sealed
關(guān)鍵字的,因此這些原本標(biāo)記 virtual
關(guān)鍵字的方法都可以重寫。
至于運(yùn)算符,本身就不可能防止重載,它的繼承和重載機(jī)制和重寫不同,所以運(yùn)算符重載是無法通過繼承來防止的。換句話說,運(yùn)算符定不定義,全看你自己的心情;心情好,你自己定義,編譯器也不會(huì)管你;心情不好,也可以不管。
不過請(qǐng)記住一點(diǎn)。object
可以實(shí)例化,但 ValueType
是抽象類型,不可實(shí)例化。
Part 3 總結(jié)
是的,本文就這一點(diǎn)點(diǎn)內(nèi)容。是不是覺得文章的內(nèi)容分布有點(diǎn)不均勻?覺得有些文章內(nèi)容多,有些文章內(nèi)容少?
因?yàn)榇_實(shí),這個(gè)部分的內(nèi)容就這一點(diǎn);但是不分出來單獨(dú)講解的話,又沒有那么正式,畢竟它還是算一個(gè)很重要的知識(shí)點(diǎn)。