開閉原則與里氏替換原則
阿新 • • 發佈:2019-02-04
1.開閉原則
是面向物件設計的基本原則之一,是“可複用設計”的基礎,它的主要原則是:對擴充套件開放,對修改關閉;意思就是我們改變一個軟體時。應該通過擴充套件方式來改變軟體,而不是修改原有的程式碼。
2.里氏替換原則
里氏替換原則是說,任何基類可以出現的地方,子類一定可以出現(只有當衍生類可以替換基類,軟體單位的功能不受到影響,基類才能真正被複用,衍生類也能夠在基類的基礎上增加新的行為)。
下面我們通過建一個專案,簡單實現一下,假如一個學生養了兩隻動物,一隻狗一隻貓,需要進行餵食(過程中匯入標頭檔案的操作省略,方法在.h中的宣告也省略,請自行新增)
1.需要建立的類有:
根檢視MainViewController,負責整體的呼叫與測試
繼承自NSobject的類Animal和繼承自Animal類的子類Cat和Dog
繼承自NSObject的類Student
2.在Animal類中實現一個方法:
-(void)eat
{
NSLog(@"動物吃不同的東西");
}
然後在其子類Cat和Dog中重寫父類方法:
-(void)eat
{
[super eat];
NSLog(@"貓吃魚");
}
-(void)eat
{
[super eat];
NSLog(@"狗吃骨頭");
}
當然也要在Cat和Dog的標頭檔案中引入-(void)eat;不然Cat和Dog例項化的物件無法呼叫此方法
3.如果不使用開閉和里氏替換,則要在Student類中實現兩個餵養方法(匯入Cat和Dog的標頭檔案):
-(void)feedCat:(Cat*)cat
{
NSLog(@"學生喂貓了");
[cat eat];
}
-(void)feedDog:(Dog*)dog
{
NSLog(@"學生喂狗了");
[dog eat];
}
4.現在在MainViewController中的viewDidLoad中呼叫是這樣的:
Student *stu=[[Student alloc]init]; Dog *dog=[[Dog alloc]init]; Cat *cat=[[Cat alloc]init]; [stu feedCat:cat]; [stu feedDog:dog];
這種基本實現方式是可以的,也能實現,但是如果學生又餵了一隻烏龜,則又需要在Student中新增給烏龜餵食的方法,這種頻繁修改原始碼的方式不太可取,下面我們用上開閉原則和里氏替換原則,重複3和4的步驟;
3.只需要在Student類中實現一個餵養方法(匯入Animal的標頭檔案):
-(void)feed:(Animal*)animal
{
NSLog(@"學生餵動物了");
[animal eat];
}
4.在MainViewController中的viewDidLoad中需要這樣呼叫:Student *stu=[[Student alloc]init];
Animal *aCat=[[Cat alloc]init];
Animal *aDog=[[Dog alloc]init];
[stu feed:aCat];
[stu feed:aDog];
這樣即使學生再餵養N只動物,Student裡面的程式碼也不需要再去修改(滿足了上面所說的開閉原則),大大減少了工作量,保持了程式碼的完整性;
這兩行
Animal *aCat=[[Cat alloc]init];
Animal *aDog=[[Dog alloc]init];
就是里氏替換,其本質就是用子類去例項化父類宣告的物件(即父類的指標指向子類開闢記憶體),然後呼叫子類內部的方法等。