面試的時候經常會被問到一個弱智題:面向對象的三個基本特征是什么?
這時候你完全可以以請教的口氣優雅的反問一道題,看看ta對“繼承”的理解(不過這駁考官面子的后果可得想清楚哦!):
classFather{publicvirtualvoidfun(){Console.WriteLine("你好!");}} classSon:Father{publicoverridevoidfun(){Console.WriteLine("Hello!");}} 上面兩個類是繼承關系嗎?談談你對繼承的理解,并用面向對象的思想改寫代碼。
好了,先賣個關子不說答案是,先來看看什么是里氏替換原則。
里氏替換原則
定義:如果對每一個類型為T1的對象o1,都有類型為T2的對象o2,使得以T1定義的所有程序P在所有的對象o1都換成o2時,程序P的行為沒有變化,那么類型T2是類型T1的子類型。
通俗的定義:所有引用基類的地方必須能透明地使用其子類的對象。
按照我的理解就是:父親能干是事情,兒子都能干;父親干不了的,兒子也能干;所有父親要干的事情,都可以讓兒子去干。
(所以對于上面的問題,我的回答是:這算不上繼承,因為父親說的是漢語,但是兒子只會說英語,我們是心中有對象的人,這違背了里氏替換原則,應該將子類的override換乘new)
第三只眼:
abstractclassPerson{//也可以不加virtual,但無virtual的情況下派生類能可以被覆蓋,但不可以被重寫。//更多virtual和override的區別略...publicvirtualvoidDoSomething(){Console.WriteLine("制造勞動工具!");//這是人和動物的基本區別}}
//***************************************************************************
classWoman:Person{overridepublicvoidDoSomething(){Console.WriteLine("生小孩!");}}
//***************************************************************************
classPRogram{staticvoidMain(string[]args){Personp=newWoman();//用子類去替換父類p.DoSomething(); Womanw=newWoman();w.DoSomething();Console.ReadKey();}}
運行結果:(人) 生小孩!
(女人)生小孩!
不是人人都能生小孩的,用子類替換父類后,這明顯違背了常理,這也違背了里氏替換原則的“子類可以實現父類的抽象方法,但是不能覆蓋父類的非抽象方法”的思想。
這時候我們可以用new去隱藏父類的方法,讓person繼續干person的事,把生小孩的事情留給woman:
classWoman:Person{newpublicvoidDoSomething()//或publicnewvoidDoSomething(){Console.WriteLine("生小孩!");}}
在思考一個關于女孩與女人的問題:
按照常規思維,女孩屬于女人,所以女孩繼承自女人。
接著上面&hell女孩對女人這個類進行了擴展,但是問題就出來了,這時候女孩就有了生小孩的能力,如果女人再有個大姨媽,難道女孩也要繼承?這時如果讓女人繼承自女孩好像更妥,女孩可以唱歌,而女人可以唱歌、生小孩、來個例假什么的。。。雖然這沒有違背面向對象繼承的任何原則,但卻不適合用常規思維去定義面向對象的類。總結:被override重寫的類最好是sealed類,即該類不能再派生子類。不要用感性的常規思維去理解面向對象的繼承,對于類的定義與繼承一定要準確且不違背常理。歡迎指點,扔便便。。。 QQ:498576940
新聞熱點
疑難解答