版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第7章繼承與接口習(xí)題:7-1面向?qū)ο蟪绦蛟O(shè)計(jì)語言的3個(gè)基本特征是什么?7-2基類能夠訪問派生類的成員嗎?反之,派生類能夠訪問基類的成員嗎?7-3創(chuàng)建TwoDShape類的派生類Circle,要求包括計(jì)算圓形面積的方法area()和使用base關(guān)鍵字初始化TwoDShape部分的構(gòu)造函數(shù)。7-4如何防止派生類訪問基類的成員?7-5請(qǐng)簡(jiǎn)述base關(guān)鍵字的作用。7-6如何防止一個(gè)類被繼承?7-7“一個(gè)接口,多種方法”是C#的關(guān)鍵原則。哪個(gè)特性最好地證明了這條原則?7-8簡(jiǎn)述接口的意義,以及在什么情況下要使用接口。7-9一個(gè)接口可以由多少個(gè)類實(shí)現(xiàn)?一個(gè)類可以實(shí)現(xiàn)多少個(gè)接口?7-10接口能夠被繼承嗎?7-11類必須實(shí)現(xiàn)接口定義的所有成員嗎?7-12接口可以聲明構(gòu)造函數(shù)嗎?7-13創(chuàng)建一個(gè)接口,隨后編寫幾個(gè)類來實(shí)現(xiàn)這個(gè)接口,并互相調(diào)用。7-14泛型、泛型集合List<T>、IEnumerable<T>接口及yield語句的特點(diǎn)是什么?7-15什么是泛型接口和委托中的協(xié)變和逆變?請(qǐng)舉例說明。答案:7-1面向?qū)ο蟪绦蛟O(shè)計(jì)語言的3個(gè)基本特征是什么?面向?qū)ο蟪绦蛟O(shè)計(jì)語言的3個(gè)基本特征是封裝、繼承和多態(tài)。封裝:將對(duì)象的屬性和行為(方法)結(jié)合在一起,形成一個(gè)獨(dú)立的整體,隱藏對(duì)象的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),只對(duì)外提供有限的訪問接口(如public屬性和方法),控制外部對(duì)對(duì)象的訪問,提高代碼的安全性和可維護(hù)性。例如,一個(gè)“學(xué)生”類封裝了學(xué)生的姓名、年齡等屬性和學(xué)習(xí)、考試等方法,外部只能通過類提供的接口訪問這些屬性和方法,無法直接操作內(nèi)部私有成員。繼承:子類(派生類)可以繼承父類(基類)的屬性和方法,同時(shí)可以添加新的屬性和方法或重寫父類的方法,實(shí)現(xiàn)代碼的復(fù)用和擴(kuò)展。例如,“大學(xué)生”類繼承“學(xué)生”類,繼承了“學(xué)生”類的姓名、年齡等屬性和學(xué)習(xí)方法,同時(shí)可以添加“專業(yè)”屬性和“實(shí)習(xí)”方法。多態(tài):同一名稱的方法或?qū)傩栽诓煌念愔芯哂胁煌膶?shí)現(xiàn)方式,使得同一個(gè)接口可以表現(xiàn)出不同的行為。多態(tài)通常通過虛方法、抽象方法和接口實(shí)現(xiàn)。例如,“動(dòng)物”類定義了“發(fā)聲”虛方法,“貓”類和“狗”類繼承“動(dòng)物”類,分別重寫“發(fā)聲”方法,“貓”類實(shí)現(xiàn)為“喵喵叫”,“狗”類實(shí)現(xiàn)為“汪汪叫”,調(diào)用“發(fā)聲”方法時(shí),根據(jù)對(duì)象的實(shí)際類型執(zhí)行不同的實(shí)現(xiàn)。7-2基類能夠訪問派生類的成員嗎?反之,派生類能夠訪問基類的成員嗎?基類不能訪問派生類的成員:基類在定義時(shí),派生類尚未存在,基類不知道派生類會(huì)添加哪些成員,因此基類無法訪問派生類的成員(包括派生類新增的屬性、方法等)。例如,基類“Animal”定義了“Name”屬性和“Eat”方法,派生類“Dog”新增了“Breed”屬性,基類“Animal”無法訪問“Dog”類的“Breed”屬性。派生類能夠訪問基類的成員,但受訪問修飾符限制:派生類可以訪問基類的public成員和protected成員。public成員在任何地方都可訪問;protected成員只能在基類內(nèi)部和派生類內(nèi)部訪問。派生類不能訪問基類的private成員,private成員只能在基類內(nèi)部訪問。如果基類成員的訪問修飾符為internal,派生類若與基類在同一程序集,可訪問該成員;若不在同一程序集,則不能訪問。例如,基類“Person”有public屬性“Name”、protected屬性“Age”、private屬性“IDCard”,派生類“Student”繼承“Person”類,“Student”類可以訪問“Name”和“Age”屬性,但不能訪問“IDCard”屬性。7-3創(chuàng)建TwoDShape類的派生類Circle,要求包括計(jì)算圓形面積的方法area()和使用base關(guān)鍵字初始化TwoDShape部分的構(gòu)造函數(shù)csharpusingSystem;//基類:TwoDShape(二維圖形)classTwoDShape{protecteddoublewidth;//寬度protecteddoubleheight;//高度//基類構(gòu)造函數(shù)publicTwoDShape(doublewidth,doubleheight){this.width=width;this.height=height;Console.WriteLine("TwoDShape構(gòu)造函數(shù)被調(diào)用");}//顯示二維圖形的尺寸publicvoidShowDimensions(){Console.WriteLine("寬度:"+width+",高度:"+height);}}//派生類:Circle(圓形),繼承TwoDShapeclassCircle:TwoDShape{//圓形的半徑(利用基類的width或height作為半徑,此處用width)publicdoubleRadius{get{returnwidth;}}//派生類構(gòu)造函數(shù),使用base關(guān)鍵字調(diào)用基類構(gòu)造函數(shù)publicCircle(doubleradius):base(radius,radius)//圓形的寬度和高度都為半徑{Console.WriteLine("Circle構(gòu)造函數(shù)被調(diào)用");}//計(jì)算圓形面積的方法publicdoubleArea(){returnMath.PI*Radius*Radius;//面積公式:πr2}}classProgram{staticvoidMain(){//創(chuàng)建Circle對(duì)象Circlecircle=newCircle(5);//調(diào)用基類的方法顯示尺寸circle.ShowDimensions();//計(jì)算并顯示圓形面積Console.WriteLine("圓形半徑:"+circle.Radius);Console.WriteLine("圓形面積:"+circle.Area());}}運(yùn)行結(jié)果:plaintextTwoDShape構(gòu)造函數(shù)被調(diào)用Circle構(gòu)造函數(shù)被調(diào)用寬度:5,高度:5圓形半徑:5圓形面積:78.539816339744837-4如何防止派生類訪問基類的成員?要防止派生類訪問基類的成員,只需將基類的成員訪問修飾符設(shè)置為private即可。private修飾符表示成員只能在基類內(nèi)部被訪問,基類的派生類(即使是直接派生類)也無法訪問該成員。示例:csharpusingSystem;//基類classBaseClass{//private成員:派生類無法訪問privatestringprivateField="基類私有字段";//public成員:派生類可訪問publicstringPublicField="基類公有字段";//private方法:派生類無法訪問privatevoidPrivateMethod(){Console.WriteLine("基類私有方法:"+privateField);}//public方法:派生類可訪問publicvoidPublicMethod(){Console.WriteLine("基類公有方法:"+PublicField);PrivateMethod();//基類內(nèi)部可訪問private成員}}//派生類classDerivedClass:BaseClass{publicvoidAccessBaseMembers(){//可以訪問基類的public成員Console.WriteLine("派生類訪問基類公有字段:"+PublicField);PublicMethod();//無法訪問基類的private成員(編譯錯(cuò)誤)//Console.WriteLine(privateField);//PrivateMethod();}}classProgram{staticvoidMain(){DerivedClassderived=newDerivedClass();derived.AccessBaseMembers();}}在上述示例中,基類的privateField字段和PrivateMethod方法被設(shè)置為private,派生類DerivedClass無法訪問這些成員;而PublicField字段和PublicMethod方法被設(shè)置為public,派生類可以正常訪問。7-5請(qǐng)簡(jiǎn)述base關(guān)鍵字的作用。base關(guān)鍵字在C#中主要用于從派生類中訪問基類的成員,具有以下兩個(gè)核心作用:調(diào)用基類的構(gòu)造函數(shù):在派生類的構(gòu)造函數(shù)中,使用“base(參數(shù)列表)”的形式可以顯式調(diào)用基類的構(gòu)造函數(shù),用于初始化從基類繼承的成員變量。如果派生類構(gòu)造函數(shù)未顯式調(diào)用基類構(gòu)造函數(shù),編譯器會(huì)自動(dòng)調(diào)用基類的無參構(gòu)造函數(shù)(若基類存在無參構(gòu)造函數(shù))。通過這種方式,確?;惖某跏蓟壿嬙谂缮惓跏蓟皥?zhí)行,避免基類成員未正確初始化的問題。示例:csharpclassBase{protectedintvalue;publicBase(intvalue){this.value=value;}}classDerived:Base{publicDerived(intvalue):base(value)//調(diào)用基類帶參構(gòu)造函數(shù){}}訪問基類的成員(屬性、方法等):在派生類中,如果派生類的成員與基類的成員同名(如派生類重寫了基類的方法),使用base關(guān)鍵字可以顯式訪問基類的成員,避免命名沖突導(dǎo)致的歧義。base關(guān)鍵字只能訪問基類的public、protected成員,無法訪問private成員。示例:csharpclassBase{publicvirtualvoidShow(){Console.WriteLine("BaseClass");}}classDerived:Base{publicoverridevoidShow(){base.Show();//調(diào)用基類的Show方法Console.WriteLine("DerivedClass");}}當(dāng)調(diào)用Derived類的Show方法時(shí),會(huì)先執(zhí)行基類Base的Show方法,再執(zhí)行派生類自身的邏輯。7-6如何防止一個(gè)類被繼承?在C#中,要防止一個(gè)類被繼承,只需在類的聲明前添加sealed關(guān)鍵字即可。sealed(密封)類表示該類不能作為基類,任何嘗試?yán)^承密封類的代碼都會(huì)導(dǎo)致編譯錯(cuò)誤。示例:csharpusingSystem;//密封類:不能被繼承sealedclassSealedClass{publicvoidShowMessage(){Console.WriteLine("這是一個(gè)密封類,不能被繼承!");}}//嘗試?yán)^承密封類(編譯錯(cuò)誤)//classDerivedClass:SealedClass//{//}classProgram{staticvoidMain(){//可以創(chuàng)建密封類的對(duì)象SealedClasssealedObj=newSealedClass();sealedObj.ShowMessage();}}在上述示例中,SealedClass被聲明為密封類,任何類(如DerivedClass)試圖繼承它時(shí),編譯器會(huì)報(bào)錯(cuò)。密封類的主要作用是防止類的繼承層次結(jié)構(gòu)被進(jìn)一步擴(kuò)展,確保類的行為不會(huì)被派生類修改,常用于一些功能穩(wěn)定、不希望被擴(kuò)展的類(如系統(tǒng)提供的string類就是密封類)。7-7“一個(gè)接口,多種方法”是C#的關(guān)鍵原則。哪個(gè)特性最好地證明了這條原則?“一個(gè)接口,多種方法”這一原則在C#中最典型的體現(xiàn)是多態(tài)性,尤其是通過接口實(shí)現(xiàn)的多態(tài)。接口定義了一組方法簽名(即“一個(gè)接口”),但不提供具體實(shí)現(xiàn);多個(gè)不同的類可以實(shí)現(xiàn)同一個(gè)接口,并根據(jù)自身需求提供不同的方法實(shí)現(xiàn)(即“多種方法”)。當(dāng)通過接口類型的引用調(diào)用方法時(shí),程序會(huì)根據(jù)對(duì)象的實(shí)際類型執(zhí)行對(duì)應(yīng)的實(shí)現(xiàn),從而實(shí)現(xiàn)“一個(gè)接口,多種方法”的效果。示例:csharpusingSystem;//定義一個(gè)接口(一個(gè)接口)interfaceIShape{doubleCalculateArea();//接口方法:計(jì)算面積}//類1實(shí)現(xiàn)接口,提供圓形面積計(jì)算(多種方法之一)classCircle:IShape{privatedoubleradius;publicCircle(doubleradius){this.radius=radius;}//實(shí)現(xiàn)接口方法:圓形面積公式πr2publicdoubleCalculateArea(){returnMath.PI*radius*radius;}}//類2實(shí)現(xiàn)接口,提供矩形面積計(jì)算(多種方法之二)classRectangle:IShape{privatedoublewidth;privatedoubleheight;publicRectangle(doublewidth,doubleheight){this.width=width;this.height=height;}//實(shí)現(xiàn)接口方法:矩形面積公式長(zhǎng)×寬publicdoubleCalculateArea(){returnwidth*height;}}classProgram{staticvoidMain(){//接口類型引用指向不同實(shí)現(xiàn)類的對(duì)象IShapeshape1=newCircle(5);IShapeshape2=newRectangle(4,6);//調(diào)用同一接口方法,執(zhí)行不同實(shí)現(xiàn)(多種方法)Console.WriteLine("圓形面積:"+shape1.CalculateArea());Console.WriteLine("矩形面積:"+shape2.CalculateArea());}}運(yùn)行結(jié)果:plaintext圓形面積:78.53981633974483矩形面積:24上述示例中,IShape接口定義了“計(jì)算面積”的統(tǒng)一接口,Circle和Rectangle類分別實(shí)現(xiàn)該接口,提供了不同的面積計(jì)算方法。通過接口類型IShape的引用調(diào)用CalculateArea()時(shí),會(huì)根據(jù)對(duì)象實(shí)際類型執(zhí)行對(duì)應(yīng)的實(shí)現(xiàn),完美體現(xiàn)“一個(gè)接口,多種方法”的原則。7-8簡(jiǎn)述接口的意義,以及在什么情況下要使用接口。一、接口的意義定義統(tǒng)一協(xié)議:接口規(guī)定了類或結(jié)構(gòu)必須實(shí)現(xiàn)的方法、屬性、事件等成員簽名,形成一套統(tǒng)一的“協(xié)議”。無論實(shí)現(xiàn)類的內(nèi)部邏輯如何,只要遵循接口協(xié)議,就能保證對(duì)外提供一致的訪問方式,降低模塊間的耦合度。實(shí)現(xiàn)多態(tài):多個(gè)不同的類可以實(shí)現(xiàn)同一個(gè)接口,通過接口類型的引用調(diào)用方法時(shí),會(huì)根據(jù)對(duì)象實(shí)際類型執(zhí)行對(duì)應(yīng)的實(shí)現(xiàn),靈活體現(xiàn)多態(tài)特性,提高代碼的擴(kuò)展性和可維護(hù)性。解決單一繼承限制:C#不支持類的多重繼承,但一個(gè)類可以實(shí)現(xiàn)多個(gè)接口。通過接口,類可以間接獲得多個(gè)“功能特性”,彌補(bǔ)單一繼承的不足。例如,一個(gè)“學(xué)生”類既可以實(shí)現(xiàn)IStudy接口(學(xué)習(xí)功能),也可以實(shí)現(xiàn)ISports接口(運(yùn)動(dòng)功能)。支持解耦開發(fā):在團(tuán)隊(duì)協(xié)作或大型項(xiàng)目中,接口可以作為模塊間的“契約”。開發(fā)人員只需關(guān)注接口定義的功能,無需了解實(shí)現(xiàn)細(xì)節(jié),實(shí)現(xiàn)“面向接口編程”,便于并行開發(fā)和后期維護(hù)(如替換接口的實(shí)現(xiàn)類時(shí),調(diào)用方代碼無需修改)。二、使用接口的場(chǎng)景需要統(tǒng)一多個(gè)類的對(duì)外接口時(shí):當(dāng)多個(gè)類(如Circle、Rectangle、Triangle)都需要提供“計(jì)算面積”和“繪制圖形”的功能時(shí),可定義IShape接口,統(tǒng)一方法簽名,確保調(diào)用方用相同方式訪問不同類的功能。類需要具備多個(gè)獨(dú)立功能特性時(shí):例如,一個(gè)“智能設(shè)備”類需要同時(shí)具備“聯(lián)網(wǎng)”(IConnect接口)、“播放媒體”(IMediaPlay接口)和“接收指令”(ICommand接口)功能,此時(shí)通過實(shí)現(xiàn)多個(gè)接口可靈活組合這些特性,避免單一繼承的局限性。模塊間需要解耦時(shí):在分層架構(gòu)(如UI層、業(yè)務(wù)邏輯層、數(shù)據(jù)訪問層)中,業(yè)務(wù)邏輯層可定義IDataAccess接口(數(shù)據(jù)訪問接口),數(shù)據(jù)訪問層提供SqlDataAccess(SQL數(shù)據(jù)庫實(shí)現(xiàn))和MongoDataAccess(MongoDB實(shí)現(xiàn))。UI層只需依賴IDataAccess接口,無需關(guān)心數(shù)據(jù)存儲(chǔ)細(xì)節(jié),后期替換數(shù)據(jù)存儲(chǔ)方式時(shí),UI層代碼無需修改。需要為不相關(guān)的類提供共性功能時(shí):例如,Person類(人員)和Company類(公司)都需要“獲取唯一標(biāo)識(shí)”的功能,可定義IHasId接口(包含GetId()方法),讓兩個(gè)不相關(guān)的類實(shí)現(xiàn)該接口,統(tǒng)一獲取標(biāo)識(shí)的方式。7-9一個(gè)接口可以由多少個(gè)類實(shí)現(xiàn)?一個(gè)類可以實(shí)現(xiàn)多少個(gè)接口?一個(gè)接口可以由無數(shù)個(gè)類實(shí)現(xiàn):接口僅定義方法、屬性等成員的簽名,不限制實(shí)現(xiàn)類的數(shù)量。只要類遵循接口的協(xié)議(實(shí)現(xiàn)接口的所有成員),任何類都可以實(shí)現(xiàn)該接口。例如,IShape接口(計(jì)算面積)可以被Circle、Rectangle、Triangle、Trapezoid等無數(shù)個(gè)表示圖形的類實(shí)現(xiàn)。一個(gè)類可以實(shí)現(xiàn)多個(gè)接口:C#支持類實(shí)現(xiàn)多個(gè)接口,以逗號(hào)分隔接口名稱,從而組合多個(gè)接口的功能特性,彌補(bǔ)類“單一繼承”的限制。例如,一個(gè)SmartPhone類可以同時(shí)實(shí)現(xiàn)IConnect(聯(lián)網(wǎng))、IMedia(媒體播放)、ICamera(拍照)三個(gè)接口,具備三種獨(dú)立功能。示例:csharpusingSystem;//定義3個(gè)獨(dú)立接口interfaceIConnect{voidConnectNetwork();//聯(lián)網(wǎng)功能}interfaceIMedia{voidPlayMusic();//播放音樂功能}interfaceICamera{voidTakePhoto();//拍照功能}//一個(gè)類實(shí)現(xiàn)多個(gè)接口classSmartPhone:IConnect,IMedia,ICamera{//實(shí)現(xiàn)IConnect接口publicvoidConnectNetwork(){Console.WriteLine("手機(jī)連接Wi-Fi網(wǎng)絡(luò)");}//實(shí)現(xiàn)IMedia接口publicvoidPlayMusic(){Console.WriteLine("手機(jī)播放音樂");}//實(shí)現(xiàn)ICamera接口publicvoidTakePhoto(){Console.WriteLine("手機(jī)拍攝照片");}}//另一個(gè)類實(shí)現(xiàn)IConnect接口(一個(gè)接口被多個(gè)類實(shí)現(xiàn))classLaptop:IConnect{publicvoidConnectNetwork(){Console.WriteLine("筆記本電腦連接以太網(wǎng)");}}classProgram{staticvoidMain(){//一個(gè)類實(shí)現(xiàn)多個(gè)接口的調(diào)用SmartPhonephone=newSmartPhone();phone.ConnectNetwork();phone.PlayMusic();phone.TakePhoto();//一個(gè)接口被多個(gè)類實(shí)現(xiàn)的調(diào)用IConnectdevice1=newSmartPhone();IConnectdevice2=newLaptop();device1.ConnectNetwork();device2.ConnectNetwork();}}運(yùn)行結(jié)果:plaintext手機(jī)連接Wi-Fi網(wǎng)絡(luò)手機(jī)播放音樂手機(jī)拍攝照片手機(jī)連接Wi-Fi網(wǎng)絡(luò)筆記本電腦連接以太網(wǎng)7-10接口能夠被繼承嗎?接口可以被繼承,且支持多繼承(一個(gè)接口可以繼承多個(gè)父接口)。接口繼承的本質(zhì)是擴(kuò)展父接口的功能,子接口會(huì)包含父接口的所有成員簽名,實(shí)現(xiàn)子接口的類需要同時(shí)實(shí)現(xiàn)子接口和所有父接口的成員。接口繼承的規(guī)則子接口通過“:”后跟父接口名稱繼承,多個(gè)父接口用逗號(hào)分隔。子接口可以新增成員(方法、屬性等),但不能重寫父接口的成員(父接口成員僅定義簽名,無實(shí)現(xiàn)可重寫)。接口繼承具有傳遞性:若接口IC繼承IB,IB繼承IA,則IC間接繼承IA的所有成員,實(shí)現(xiàn)IC的類需同時(shí)實(shí)現(xiàn)IA、IB、IC的成員。示例:csharpusingSystem;//父接口1:基礎(chǔ)圖形接口interfaceIShape{doubleCalculateArea();//計(jì)算面積}//父接口2:可繪制接口interfaceIDrawable{voidDraw();//繪制圖形}//子接口:繼承兩個(gè)父接口,新增成員interfaceIAdvancedShape:IShape,IDrawable{voidResize(doublescale);//新增“縮放圖形”功能}//實(shí)現(xiàn)子接口(需實(shí)現(xiàn)所有父接口和子接口的成員)classCircle:IAdvancedShape{privatedoubleradius;publicCircle(doubleradius){this.radius=radius;}//實(shí)現(xiàn)IShape接口的CalculateAreapublicdoubleCalculateArea(){returnMath.PI*radius*radius;}//實(shí)現(xiàn)IDrawable接口的DrawpublicvoidDraw(){Console.WriteLine($"繪制半徑為{radius}的圓形");}//實(shí)現(xiàn)IAdvancedShape接口的ResizepublicvoidResize(doublescale){radius*=scale;Console.WriteLine($"圓形縮放至半徑{radius}");}}classProgram{staticvoidMain(){IAdvancedShapecircle=newCircle(5);circle.Draw();Console.WriteLine("圓形面積:"+circle.CalculateArea());circle.Resize(1.5);Console.WriteLine("縮放后面積:"+circle.CalculateArea());}}運(yùn)行結(jié)果:plaintext繪制半徑為5的圓形圓形面積:78.53981633974483圓形縮放至半徑7.5縮放后面積:176.714586764425867-11類必須實(shí)現(xiàn)接口定義的所有成員嗎?是的,類必須實(shí)現(xiàn)接口定義的所有成員(方法、屬性、事件、索引器等),否則類必須聲明為abstract(抽象類),由抽象類的派生類完成未實(shí)現(xiàn)的接口成員。具體規(guī)則非抽象類:必須顯式實(shí)現(xiàn)接口的所有成員,包括成員的簽名、返回值類型和訪問修飾符(接口成員默認(rèn)public,實(shí)現(xiàn)時(shí)也需用public修飾)。若遺漏任何成員,編譯器會(huì)報(bào)錯(cuò)。抽象類:可以選擇實(shí)現(xiàn)部分接口成員,未實(shí)現(xiàn)的成員需聲明為abstract抽象方法,由抽象類的非抽象派生類最終實(shí)現(xiàn)。示例1:非抽象類實(shí)現(xiàn)接口(必須實(shí)現(xiàn)所有成員)csharpusingSystem;interfaceIUser{stringGetName();//方法1intGetAge();//方法2}//非抽象類:必須實(shí)現(xiàn)IUser的所有成員classStudent:IUser{privatestringname;privateintage;publicStudent(stringname,intage){=name;this.age=age;}//實(shí)現(xiàn)GetNamepublicstringGetName(){returnname;}//實(shí)現(xiàn)GetAge(若遺漏此方法,編譯器報(bào)錯(cuò))publicintGetAge(){returnage;}}示例2:抽象類實(shí)現(xiàn)接口(可部分實(shí)現(xiàn))csharpusingSystem;interfaceIUser{stringGetName();intGetAge();}//抽象類:實(shí)現(xiàn)GetName,GetAge聲明為抽象方法abstractclassAbstractUser:IUser{protectedstringname;publicAbstractUser(stringname){=name;}//實(shí)現(xiàn)GetNamepublicstringGetName(){returnname;}//未實(shí)現(xiàn)GetAge,聲明為抽象方法publicabstractintGetAge();}//非抽象派生類:實(shí)現(xiàn)抽象方法GetAgeclassTeacher:AbstractUser{privateintage;publicTeacher(stringname,intage):base(name){this.age=age;}//實(shí)現(xiàn)抽象方法GetAgepublicoverrideintGetAge(){returnage;}}classProgram{staticvoidMain(){IUserteacher=newTeacher("張老師",35);Console.WriteLine("姓名:"+teacher.GetName());Console.WriteLine("年齡:"+teacher.GetAge());}}運(yùn)行結(jié)果:plaintext姓名:張老師年齡:357-12接口可以聲明構(gòu)造函數(shù)嗎?不可以,接口不能聲明構(gòu)造函數(shù)。原因接口的本質(zhì)是“協(xié)議”:接口僅定義類或結(jié)構(gòu)必須實(shí)現(xiàn)的成員簽名,不包含任何實(shí)例狀態(tài)或初始化邏輯。構(gòu)造函數(shù)的作用是初始化類的實(shí)例(如給成員變量賦值),屬于類的具體實(shí)現(xiàn)細(xì)節(jié),不符合接口“只定義協(xié)議、不包含實(shí)現(xiàn)”的定位。接口無法實(shí)例化:構(gòu)造函數(shù)在創(chuàng)建類的實(shí)例時(shí)自動(dòng)調(diào)用,但接口本身不能被實(shí)例化(無法用new關(guān)鍵字創(chuàng)建接口對(duì)象),因此聲明構(gòu)造函數(shù)沒有實(shí)際意義。實(shí)現(xiàn)類負(fù)責(zé)初始化:接口的實(shí)現(xiàn)類會(huì)通過自身的構(gòu)造函數(shù)完成實(shí)例初始化,若接口允許聲明構(gòu)造函數(shù),會(huì)導(dǎo)致初始化邏輯混亂(如多個(gè)實(shí)現(xiàn)類需遵循接口構(gòu)造函數(shù)的約束,違背接口的靈活性)。錯(cuò)誤示例(接口聲明構(gòu)造函數(shù)):csharp//編譯錯(cuò)誤:接口不能包含構(gòu)造函數(shù)interfaceIShape{//錯(cuò)誤:接口中不允許聲明構(gòu)造函數(shù)IShape(doubleradius);doubleCalculateArea();}正確做法(實(shí)現(xiàn)類聲明構(gòu)造函數(shù)):csharpusingSystem;interfaceIShape{doubleCalculateArea();}//實(shí)現(xiàn)類聲明構(gòu)造函數(shù),完成初始化classCircle:IShape{privatedoubleradius;//構(gòu)造函數(shù):初始化半徑publicCircle(doubleradius){this.radius=radius;}publicdoubleCalculateArea(){returnMath.PI*radius*radius;}}7-13創(chuàng)建一個(gè)接口,隨后編寫幾個(gè)類來實(shí)現(xiàn)這個(gè)接口,并互相調(diào)用。步驟1:定義接口定義IEmployee接口,包含“獲取員工信息”和“計(jì)算月薪”的方法簽名:csharpusingSystem;//定義員工接口interfaceIEmployee{stringGetInfo();//獲取員工基本信息doubleCalculateSalary();//計(jì)算月薪}步驟2:編寫實(shí)現(xiàn)類創(chuàng)建3個(gè)實(shí)現(xiàn)類:FullTimeEmployee(全職員工)、PartTimeEmployee(兼職員工)、Manager(經(jīng)理,繼承全職員工并擴(kuò)展),分別實(shí)現(xiàn)IEmployee接口的方法:csharp//1.全職員工類:實(shí)現(xiàn)IEmployee接口classFullTimeEmployee:IEmployee{protectedstringname;protectedintid;protecteddoublebasicSalary;//基本工資publicFullTimeEmployee(stringname,intid,doublebasicSalary){=name;this.id=id;this.basicSalary=basicSalary;}//實(shí)現(xiàn)GetInfo:返回員工基本信息publicvirtualstringGetInfo(){return$"ID:{id},姓名:{name},類型:全職員工";}//實(shí)現(xiàn)CalculateSalary:全職員工月薪=基本工資publicvirtualdoubleCalculateSalary(){returnbasicSalary;}}//2.兼職員工類:實(shí)現(xiàn)IEmployee接口classPartTimeEmployee:IEmployee{privatestringname;privateintid;privatedoublehourlyWage;//時(shí)薪privateintworkHours;//月工作時(shí)長(zhǎng)publicPartTimeEmployee(stringname,intid,doublehourlyWage,intworkHours){=name;this.id=id;this.hourlyWage=hourlyWage;this.workHours=workHours;}//實(shí)現(xiàn)GetInfo:返回兼職員工信息publicstringGetInfo(){return$"ID:{id},姓名:{name},類型:兼職員工,時(shí)薪:{hourlyWage}";}//實(shí)現(xiàn)CalculateSalary:兼職員工月薪=時(shí)薪×工作時(shí)長(zhǎng)publicdoubleCalculateSalary(){returnhourlyWage*workHours;}}//3.經(jīng)理類:繼承全職員工,擴(kuò)展獎(jiǎng)金邏輯classManager:FullTimeEmployee{privatedoublebonus;//獎(jiǎng)金publicManager(stringname,intid,doublebasicSalary,doublebonus):base(name,id,basicSalary){this.bonus=bonus;}//重寫GetInfo:添加經(jīng)理標(biāo)識(shí)publicoverridestringGetInfo(){returnbase.GetInfo().Replace("全職員工","經(jīng)理");}//重寫CalculateSalary:經(jīng)理月薪=基本工資+獎(jiǎng)金publicoverridedoubleCalculateSalary(){returnbase.CalculateSalary()+bonus;}}步驟3:互相調(diào)用(統(tǒng)一接口調(diào)用+類間協(xié)作)創(chuàng)建Company類(公司),包含“統(tǒng)計(jì)員工薪資”方法,通過IEmployee接口統(tǒng)一調(diào)用不同員工的方法,實(shí)現(xiàn)類間協(xié)作:csharp//公司類:統(tǒng)一管理員工,實(shí)現(xiàn)類間調(diào)用classCompany{privateList<IEmployee>employees=newList<IEmployee>();//添加員工publicvoidAddEmployee(IEmployeeemployee){employees.Add(employee);Console.WriteLine($"新增員工:{employee.GetInfo()}");}//統(tǒng)計(jì)所有員工月薪總和publicdoubleCalculateTotalSalary(){doubletotal=0;Console.WriteLine("\n===員工薪資明細(xì)===");foreach(varempinemployees){doublesalary=emp.CalculateSalary();Console.WriteLine($"{emp.GetInfo()},月薪:{salary:C}");total+=salary;}returntotal;}}classProgram{staticvoidMain(){//1.創(chuàng)建公司和員工對(duì)象Companycompany=newCompany();IEmployeeftEmp=newFullTimeEmployee("李雷",101,8000);IEmployeeptEmp=newPartTimeEmployee("韓梅梅",102,50,160);IEmployeemanager=newManager("王總",901,20000,15000);//2.添加員工(類間調(diào)用:Company調(diào)用IEmployee的GetInfo)company.AddEmployee(ftEmp);company.AddEmployee(ptEmp);company.AddEmployee(manager);//3.統(tǒng)計(jì)薪資(類間調(diào)用:Company調(diào)用IEmployee的CalculateSalary)doubletotal=company.CalculateTotalSalary();Console.WriteLine($"===公司月薪資總額:{total:C}===");//4.子類間調(diào)用(Manager調(diào)用父類FullTimeEmployee的方法)Managermgr=(Manager)manager;Console.WriteLine("\n經(jīng)理詳細(xì)信息:"+mgr.GetInfo());Console.WriteLine("經(jīng)理基本工資:"+(mgr.CalculateSalary()-15000:C));}}運(yùn)行結(jié)果plaintext新增員工:ID:101,姓名:李雷,類型:全職員工新增員工:ID:102,姓名:韓梅梅,類型:兼職員工,時(shí)薪:50新增員工:ID:901,姓名:王總,類型:經(jīng)理===員工薪資明細(xì)===ID:101,姓名:李雷,類型:全職員工,月薪:¥8,000.00ID:102,姓名:韓梅梅,類型:兼職員工,時(shí)薪:50,月薪:¥8,000.00ID:901,姓名:王總,類型:經(jīng)理,月薪:¥35,000.00===公司月薪資總額:¥51,000.00===經(jīng)理詳細(xì)信息:ID:901,姓名:王總,類型:經(jīng)理經(jīng)理基本工資:¥20,000.007-14泛型、泛型集合List<T>、IEnumerable<T>接口及yield語句的特點(diǎn)是什么?一、泛型的特點(diǎn)類型參數(shù)化:泛型允許將數(shù)據(jù)類型作為“參數(shù)”傳遞給類、方法或接口,如List<T>中的T,在使用時(shí)才確定具體類型(如List<int>、List<string>),實(shí)現(xiàn)“一套代碼,多種類型復(fù)用”。類型安全:編譯時(shí)檢查類型兼容性,避免運(yùn)行時(shí)類型轉(zhuǎn)換錯(cuò)誤。例如,List<int>只能存儲(chǔ)int類型數(shù)據(jù),無法添加string類型,相比非泛型集合(如ArrayList)更安全。減少裝箱/拆箱:值類型(如int)存儲(chǔ)在泛型集合中時(shí),無需裝箱為object;讀取時(shí)無需拆箱,提升性能。非泛型集合(如ArrayList)存儲(chǔ)值類型時(shí)會(huì)頻繁裝箱/拆箱,消耗性能。代碼復(fù)用:泛型類/方法可適配多種數(shù)據(jù)類型,無需為每種類型編寫重復(fù)代碼。例如,Swap<T>(refTa,refTb)方法可交換任意類型的兩個(gè)變量。二、泛型集合List<T>的特點(diǎn)強(qiáng)類型集合:繼承自IList<T>接口,僅存儲(chǔ)指定類型T的數(shù)據(jù),編譯時(shí)保證類型安全,避免非泛型集合(如ArrayList)的類型轉(zhuǎn)換風(fēng)險(xiǎn)。動(dòng)態(tài)擴(kuò)容:默認(rèn)初始容量為4,當(dāng)元素?cái)?shù)量超過容量時(shí),自動(dòng)擴(kuò)容為原容量的2倍(通過重新分配數(shù)組實(shí)現(xiàn)),無需手動(dòng)管理容量。豐富的成員方法:提供Add()(添加元素)、Insert()(插入元素)、Remove()(刪除元素)、Sort()(排序)、Find()(查找)、ToArray()(轉(zhuǎn)為數(shù)組)等方法,滿足常見集合操作需求。高效訪問:基于數(shù)組實(shí)現(xiàn),通過索引(如list[0])訪問元素,時(shí)間復(fù)雜度為O(1),查詢效率高;插入/刪除元素(尤其是中間位置)需移動(dòng)數(shù)組元素,時(shí)間復(fù)雜度為O(n)。泛型兼容性:實(shí)現(xiàn)IEnumerable<T>接口,支持foreach遍歷;可與LINQ(語言集成查詢)結(jié)合,簡(jiǎn)化數(shù)據(jù)篩選、排序等操作。三、IEnumerable<T>接口的特點(diǎn)泛型遍歷協(xié)議:定義了“獲取枚舉器”的統(tǒng)一接口,包含GetEnumerator()方法,返回IEnumerator<T>類型的枚舉器,支持對(duì)泛型集合的遍歷。支持foreach遍歷:任何實(shí)現(xiàn)IEnumerable<T>的集合(如List<T>、HashSet<T>)都可使用foreach循環(huán)遍歷,無需手動(dòng)管理索引。延遲執(zhí)行:配合yield語句使用時(shí),可實(shí)現(xiàn)“按需生成”數(shù)據(jù),而非一次性加載所有數(shù)據(jù),減少內(nèi)存占用。例如,生成無限序列(如自然數(shù)序列)時(shí),僅在遍歷到該元素時(shí)才計(jì)算其值。繼承自IEnumerable:泛型接口IEnumerable<T>繼承自非泛型接口IEnumerable,確保與舊代碼的兼容性,同時(shí)提供泛型類型安全。四、yield語句的特點(diǎn)簡(jiǎn)化迭代器實(shí)現(xiàn):無需手動(dòng)實(shí)現(xiàn)IEnumerator<T>接口的Current屬性、MoveNext()方法和Dispose()方法,通過yieldreturn和yieldbreak語句自動(dòng)生成迭代器邏輯。延遲執(zhí)行:yieldreturn語句返回一個(gè)元素后,暫停方法執(zhí)行;下次調(diào)用MoveNext()時(shí),從暫停位置繼續(xù)執(zhí)行,實(shí)現(xiàn)“按需生成”數(shù)據(jù),節(jié)省內(nèi)存。支持無限序列:可生成無限長(zhǎng)度的序列(如GenerateNaturalNumbers()生成自然數(shù)),因延遲執(zhí)行,不會(huì)一次性加載所有元素到內(nèi)存。配合IEnumerable<T>使用:包含yield語句的方法/屬性(迭代塊)必須返回IEnumerable、IEnumerator、IEnumerable<T>或IEnumerator<T>類型,常用于實(shí)現(xiàn)自定義集合的遍歷邏輯。示例:yield語句實(shí)現(xiàn)延遲遍歷csharpusingSystem;usingSystem.Collections.Generic;classYieldDemo{//生成1~n的偶數(shù)(延遲執(zhí)行)publicstaticIEnumerable<int>GetEvenNumbers(intn){for(inti=1;i<=n;i++){if(i%2==0){yieldreturni;//返回偶數(shù),暫停執(zhí)行}}yieldbreak;//結(jié)束迭代}staticvoidMain(){//foreach遍歷:僅在訪問時(shí)生成元素foreach(intnuminGetEvenNumbers(10)){Console.Write(num+"");//輸出:246810}}}7-15什么是泛型接口和委托中的協(xié)變和逆變?請(qǐng)舉例說明。一、核心概念協(xié)變(Covariance):允許將“派生類泛型類型”隱式轉(zhuǎn)換為“基類泛型類型”,用out關(guān)鍵字標(biāo)記泛型參數(shù)(僅用于返回值類型)。例如,IEnumerable<Dog>(狗的集合)可轉(zhuǎn)換為IEnumerable<Animal>(動(dòng)物的集合)。逆變(Contravariance):允許將“基類泛型類型”隱式轉(zhuǎn)換為“派生類泛型類型”,用in關(guān)鍵字標(biāo)記泛型參數(shù)(僅用于參數(shù)類型)。例如,Action<Animal>(接收動(dòng)物的委托)可轉(zhuǎn)換為Action<Dog>(接收狗的委托)。本質(zhì):協(xié)變和逆變僅適用于引用類型,通過調(diào)整泛型類型的繼承關(guān)系,增強(qiáng)代碼靈活性,避免顯式類型轉(zhuǎn)換。二、泛型接口中的協(xié)變和逆變1.協(xié)變(out關(guān)鍵字)適用場(chǎng)景:泛型接口的方法僅返回泛型參數(shù)類型(無泛型參數(shù)作為方法參數(shù))。示例:IEnumerable<T>的協(xié)變csharpusingSystem;usingSystem.Collections.Generic;//基類classAnimal{publicstringName{get;set;}}//派生類classDog:Animal{publicvoidBark(){Console.WriteLine($"{Name}在叫:汪汪!");}}classCovarianceDemo{staticvoidMain(){//1.創(chuàng)建派生類泛型集合List<Dog>dogs=newList<Dog>{newDog{Name="旺財(cái)"},newDog{Name="小白"}};//2.協(xié)變:List<Dog>→IEnumerable<Animal>(隱式轉(zhuǎn)換)//原因:IEnumerable<T>的T標(biāo)記為out,支持協(xié)變IEnumerable<Animal>animals=dogs;//3.遍歷基類接口,實(shí)際訪問派生類對(duì)象foreach(Animalanimalinanimals){//顯式轉(zhuǎn)換為Dog,調(diào)用派生類方法if(animalisDogdog){dog.Bark();}}}}運(yùn)行結(jié)果:plaintext旺財(cái)在叫:汪汪!小白在叫:汪汪!2.逆變(in關(guān)鍵字)適用場(chǎng)景:泛型接口的方法僅接收泛型參數(shù)類型(無泛型參數(shù)作為返回值)。示例:IComparer<T>的逆變csharpusingSystem;usingSystem.Collections.Generic;clas
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 加油站卸油時(shí)跑冒油應(yīng)急演練及方案
- 安徽滁州市鳳陽縣2025-2026學(xué)年第一學(xué)期期末考試九年級(jí)道德與法治試卷(含答案)
- 河南省許昌市鄢陵縣彭店二中2025-2026學(xué)年九年級(jí)上冊(cè)英語期末試卷(含答案無聽力原文及音頻 )
- 2025年渠縣幼兒園教師招教考試備考題庫含答案解析(必刷)
- 2025年三亞城市職業(yè)學(xué)院馬克思主義基本原理概論期末考試模擬題附答案解析(必刷)
- 2025年畢節(jié)職業(yè)技術(shù)學(xué)院?jiǎn)握新殬I(yè)技能測(cè)試題庫帶答案解析
- 2025年漳縣招教考試備考題庫附答案解析(必刷)
- 2024年郴州思科職業(yè)學(xué)院馬克思主義基本原理概論期末考試題含答案解析(奪冠)
- 2024年銅川職業(yè)技術(shù)學(xué)院馬克思主義基本原理概論期末考試題含答案解析(奪冠)
- 2025年貴南縣幼兒園教師招教考試備考題庫含答案解析(奪冠)
- 湖南雅禮高一數(shù)學(xué)試卷
- CNAS-GC25-2023 服務(wù)認(rèn)證機(jī)構(gòu)認(rèn)證業(yè)務(wù)范圍及能力管理實(shí)施指南
- 入伍智力測(cè)試題及答案
- 竣工驗(yàn)收方案模板
- 企業(yè)安全生產(chǎn)內(nèi)業(yè)資料全套范本
- 安全生產(chǎn)標(biāo)準(zhǔn)化與安全文化建設(shè)的關(guān)系
- DL-T5054-2016火力發(fā)電廠汽水管道設(shè)計(jì)規(guī)范
- 耳部刮痧治療
- 神經(jīng)外科介入神經(jīng)放射治療技術(shù)操作規(guī)范2023版
- 多模態(tài)數(shù)據(jù)的聯(lián)合增強(qiáng)技術(shù)
- 濱海事業(yè)單位招聘2023年考試真題及答案解析1
評(píng)論
0/150
提交評(píng)論