【移動應(yīng)用開發(fā)技術(shù)】【基本功】深入剖析Swift性能優(yōu)化_第1頁
【移動應(yīng)用開發(fā)技術(shù)】【基本功】深入剖析Swift性能優(yōu)化_第2頁
【移動應(yīng)用開發(fā)技術(shù)】【基本功】深入剖析Swift性能優(yōu)化_第3頁
【移動應(yīng)用開發(fā)技術(shù)】【基本功】深入剖析Swift性能優(yōu)化_第4頁
【移動應(yīng)用開發(fā)技術(shù)】【基本功】深入剖析Swift性能優(yōu)化_第5頁
已閱讀5頁,還剩10頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】【基本功】深入剖析Swift性能優(yōu)化

美美今天請來了我們技術(shù)團隊很厲害的iOS女神亞男小姐姐深度剖析Swift,她特別講解了如何才能開發(fā)出高性能的Swift程序。希望對你有所幫助哦~EnjoyReading!簡介2014年,蘋果公司在WWDC上發(fā)布Swift這一新的編程語言。經(jīng)過幾年的發(fā)展,Swift已經(jīng)成為iOS開發(fā)語言的“中流砥柱”,Swift提供了非常靈活的高級別特性,例如協(xié)議、閉包、泛型等,并且Swift還進一步開發(fā)了強大的SIL(SwiftIntermediateLanguage)用于對編譯器進行優(yōu)化,使得Swift相比Objective-C運行更快性能更優(yōu),Swift內(nèi)部如何實現(xiàn)性能的優(yōu)化,我們本文就進行一下解讀,希望能對大家有所啟發(fā)和幫助。針對Swift性能提升這一問題,我們可以從概念上拆分為兩個部分:編譯器:Swift編譯器進行的性能優(yōu)化,從階段分為編譯期和運行期,內(nèi)容分為時間優(yōu)化和空間優(yōu)化。開發(fā)者:通過使用合適的數(shù)據(jù)結(jié)構(gòu)和關(guān)鍵字,幫助編譯器獲取更多信息,進行優(yōu)化。下面我們將從這兩個角度切入,對Swift性能優(yōu)化進行分析。通過了解編譯器對不同數(shù)據(jù)結(jié)構(gòu)處理的內(nèi)部實現(xiàn),來選擇最合適的算法機制,并利用編譯器的優(yōu)化特性,編寫高性能的程序。理解Swift的性能,首先要清楚Swift的數(shù)據(jù)結(jié)構(gòu),組件關(guān)系和編譯運行方式。數(shù)據(jù)結(jié)構(gòu)Swift的數(shù)據(jù)結(jié)構(gòu)可以大體拆分為:Class,Struct,Enum。組件關(guān)系組件關(guān)系可以分為:inheritance,protocols,generics。方法分派方式方法分派方式可以分為Staticdispatch和Dynamicdispatch。要在開發(fā)中提高Swift性能,需要開發(fā)者去了解這幾種數(shù)據(jù)結(jié)構(gòu)和組件關(guān)系以及它們的內(nèi)部實現(xiàn),從而通過選擇最合適的抽象機制來提升性能。首先我們對于性能標準進行一個概念陳述,性能標準涵蓋三個標準:AllocationReferencecountingMethoddispatch接下來,我們會分別對這幾個指標進行說明。內(nèi)存分配可以分為堆區(qū)棧區(qū),在棧的內(nèi)存分配速度要高于堆,結(jié)構(gòu)體和類在堆棧分配是不同的。Stack基本數(shù)據(jù)類型和結(jié)構(gòu)體默認在棧區(qū),棧區(qū)內(nèi)存是連續(xù)的,通過出棧入棧進行分配和銷毀,速度很快,高于堆區(qū)。我們通過一些例子進行說明:以上結(jié)構(gòu)體的內(nèi)存是在棧區(qū)分配的,內(nèi)部的變量也是內(nèi)聯(lián)在棧區(qū)。將point1賦值給point2實際操作是在棧區(qū)進行了一份拷貝,產(chǎn)生了新的內(nèi)存消耗point2,這使得point1和point2是完全獨立的兩個實例,它們之間的操作互不影響。在使用point1和point2之后,會進行銷毀。Heap高級的數(shù)據(jù)結(jié)構(gòu),比如類,分配在堆區(qū)。初始化時查找沒有使用的內(nèi)存塊,銷毀時再從內(nèi)存塊中清除。因為堆區(qū)可能存在多線程的操作問題,為了保證線程安全,需要進行加鎖操作,因此也是一種性能消耗。以上我們初始化了一個Class類型,在棧區(qū)分配一塊內(nèi)存,但是和結(jié)構(gòu)體直接在棧內(nèi)存儲數(shù)值不同,我們只在棧區(qū)存儲了對象的指針,指針指向的對象的內(nèi)存是分配在堆區(qū)的。需要注意的是,為了管理對象內(nèi)存,在堆區(qū)初始化時,除了分配屬性內(nèi)存(這里是Double類型的x,y),還會有額外的兩個字段,分別是type和refCount,這個包含了type,refCount和實際屬性的結(jié)構(gòu)被稱為bluebox。內(nèi)存分配總結(jié)從初始化角度,Class相比Struct需要在堆區(qū)分配內(nèi)存,進行內(nèi)存管理,使用了指針,有更強大的特性,但是性能較低。優(yōu)化方式:對于頻繁操作(比如通信軟件的內(nèi)容氣泡展示),盡量使用Struct替代Class,因為棧內(nèi)存分配更快,更安全,操作更快。Swift通過引用計數(shù)管理堆對象內(nèi)存,當(dāng)引用計數(shù)為0時,Swift確認沒有對象再引用該內(nèi)存,所以將內(nèi)存釋放。對于引用計數(shù)的管理是一個非常高頻的間接操作,并且需要考慮線程安全,使得引用計數(shù)的操作需要較高的性能消耗。對于基本數(shù)據(jù)類型的Struct來說,沒有堆內(nèi)存分配和引用計數(shù)的管理,性能更高更安全,但是對于復(fù)雜的結(jié)構(gòu)體,如:這里看到,包含了引用的結(jié)構(gòu)體相比Class,需要管理雙倍的引用計數(shù)。每次將結(jié)構(gòu)體作為參數(shù)傳遞給方法或者進行直接拷貝時,都會出現(xiàn)多份引用計數(shù)。下圖可以比較直觀的理解:Class在拷貝時的處理方式:引用計數(shù)總結(jié)Class在堆區(qū)分配內(nèi)存,需要使用引用計數(shù)器進行內(nèi)存管理?;绢愋偷腟truct在棧區(qū)分配內(nèi)存,無引用計數(shù)管理。包含強類型的Struct通過指針管理在堆區(qū)的屬性,對結(jié)構(gòu)體的拷貝會創(chuàng)建新的棧內(nèi)存,創(chuàng)建多份引用的指針,Class只會有一份。優(yōu)化方式在使用結(jié)構(gòu)體時:通過使用精確類型,例如UUID替代String(UUID字節(jié)長度固定128字節(jié),而不是String任意長度),這樣就可以進行內(nèi)存內(nèi)聯(lián),在棧內(nèi)存儲UUID,我們知道,棧內(nèi)存管理更快更安全,并且不需要引用計數(shù)。Enum替代String,在棧內(nèi)管理內(nèi)存,無引用計數(shù),并且從語法上對于開發(fā)者更友好。我們之前在StaticdispatchVSDynamicdispatch中提到過,能夠在編譯期確定執(zhí)行方法的方式叫做靜態(tài)分派Staticdispatch,無法在編譯期確定,只能在運行時去確定執(zhí)行方法的分派方式叫做動態(tài)分派Dynamicdispatch。Staticdispatch更快,而且靜態(tài)分派可以進行內(nèi)聯(lián)等進一步的優(yōu)化,使得執(zhí)行更快速,性能更高。但是對于多態(tài)的情況,我們不能在編譯期確定最終的類型,這里就用到了Dynamicdispatch動態(tài)分派。動態(tài)分派的實現(xiàn)是,每種類型都會創(chuàng)建一張表,表內(nèi)是一個包含了方法指針的數(shù)組。動態(tài)分派更靈活,但是因為有查表和跳轉(zhuǎn)的操作,并且因為很多特點對于編譯器來說并不明確,所以相當(dāng)于block了編譯器的一些后期優(yōu)化。所以速度慢于Staticdispatch。下面看一段多態(tài)代碼,以及分析實現(xiàn)方式:MethodDispatch總結(jié)Class默認使用Dynamicdispatch,因為在編譯期幾乎每個環(huán)節(jié)的信息都無法確定,所以阻礙了編譯器的優(yōu)化,比如inline和wholemoduleinline。使用Staticdispatch代替Dynamicdispatch提升性能我們知道Staticdispatch快于Dynamicdispatch,如何在開發(fā)中去盡可能使用Staticdispatch。inheritanceconstraints繼承約束我們可以使用final關(guān)鍵字去修飾Class,以此生成的Finalclass,使用Staticdispatch。accesscontrol訪問控制private關(guān)鍵字修飾,使得方法或?qū)傩灾粚Ξ?dāng)前類可見。編譯器會對方法進行Staticdispatch。編譯器可以通過wholemoduleoptimization檢查繼承關(guān)系,對某些沒有標記final的類通過計算,如果能在編譯期確定執(zhí)行的方法,則使用Staticdispatch。Struct默認使用Staticdispatch。Swift快于OC的一個關(guān)鍵是可以消解動態(tài)分派??偨Y(jié)Swift提供了更靈活的Struct,用以在內(nèi)存、引用計數(shù)、方法分派等角度去進行性能的優(yōu)化,在正確的時機選擇正確的數(shù)據(jù)結(jié)構(gòu),可以使我們的代碼性能更快更安全。延伸你可能會問Struct如何實現(xiàn)多態(tài)呢?答案是protocolorientedprogramming。以上分析了影響性能的幾個標準,那么不同的算法機制Class,ProtocolTypes和Genericcode,它們在這三方面的表現(xiàn)如何,ProtocolType和Genericcode分別是怎么實現(xiàn)的呢?我們帶著這個問題看下去。這里我們會討論ProtocolType如何存儲和拷貝變量,以及方法分派是如何實現(xiàn)的。不通過繼承或者引用語義的多態(tài):以上通過ProtocolType實現(xiàn)多態(tài),幾個類之間沒有繼承關(guān)系,故不能按照慣例借助V-Table實現(xiàn)動態(tài)分派。如果想了解Vtable和Witnesstable實現(xiàn),可以進行點擊查看,這里不做細節(jié)說明。因為Point和Line的尺寸不同,數(shù)組存儲數(shù)據(jù)實現(xiàn)一致性存儲,使用了ExistentialContainer。查找正確的執(zhí)行方法則使用了ProtolocWitnessTable。ExistentialContainer是一種特殊的內(nèi)存布局方式,用于管理遵守了相同協(xié)議的數(shù)據(jù)類型ProtocolType,這些數(shù)據(jù)類型因為不共享同一繼承關(guān)系(這是V-Table實現(xiàn)的前提),并且內(nèi)存空間尺寸不同,使用ExistentialContainer進行管理,使其具有存儲的一致性。結(jié)構(gòu)如下:三個詞大小的valueBuffer這里介紹一下valueBuffer結(jié)構(gòu),valueBuffer有三個詞,每個詞包含8個字節(jié),存儲的可能是值,也可能是對象的指針。對于smallvalue(空間小于valueBuffer),直接存儲在valueBuffer的地址內(nèi),inlinevalueBuffer,無額外堆內(nèi)存初始化。當(dāng)值的數(shù)量大于3個屬性即largevalue,或者總尺寸超過valueBuffer的占位,就會在堆區(qū)開辟內(nèi)存,將其存儲在堆區(qū),valueBuffer存儲內(nèi)存指針。valuewitnesstable的引用因為ProtocolType的類型不同,內(nèi)存空間,初始化方法等都不相同,為了對ProtocolType生命周期進行專項管理,用到了ValueWitnessTtocolwitnesstable的引用管理ProtocolType的方法分派。內(nèi)存分布如下:為了實現(xiàn)Class多態(tài)也就是引用語義多態(tài),需要V-Table來實現(xiàn),但是V-Table的前提是具有同一個父類即共享相同的繼承關(guān)系,但是對于ProtocolType來說,并不具備此特征,故為了支持Struct的多態(tài),需要用到protocolorientedprogramming機制,也就是借助ProtocolWitnessTable來實現(xiàn)(細節(jié)可以點擊Vtable和witnesstable實現(xiàn),每個結(jié)構(gòu)體會創(chuàng)造PWT表,內(nèi)部包含指針,指向方法具體實現(xiàn))。用于管理任意值的初始化、拷貝、銷毀。ValueWitnessTable的結(jié)構(gòu)如上,是用于管理遵守了協(xié)議的ProtocolType實例的初始化,拷貝,內(nèi)存消減和銷毀的。ValueWitnessTable在SIL中還可以拆分為%relative_vwtable和%absolute_vwtable,我們這里先不做展開。ValueWitnessTable和ProtocolWitnessTable通過分工,去管理ProtocolType實例的內(nèi)存管理(初始化,拷貝,銷毀)和方法調(diào)用。我們來借助具體的示例進行進一步了解:在Swift編譯器中,通過ExistentialContainer實現(xiàn)的偽代碼如下:我們知道,Swift中Class的實例和屬性都存儲在堆區(qū),Struct實例在棧區(qū),如果包含指針屬性則存儲在堆區(qū),ProtocolType如何存儲屬性?SmallNumber通過ExistentialContainer內(nèi)聯(lián)實現(xiàn),大數(shù)存在堆區(qū)。如何處理Copy呢?在出現(xiàn)Copy情況時:會將新的ExsitentialContainer的valueBuffer指向同一個value即創(chuàng)建指針引用,但是如果要改變值怎么辦?我們知道Struct值的修改和Class不同,Copy是不應(yīng)該影響原實例的值的。這里用到了一個技術(shù)叫做IndirectStorageWithCopy-On-Write,即優(yōu)先使用內(nèi)存指針。通過提高內(nèi)存指針的使用,來降低堆區(qū)內(nèi)存的初始化。降低內(nèi)存消耗。在需要修改值的時候,會先檢測引用計數(shù)檢測,如果有大于1的引用計數(shù),則開辟新內(nèi)存,創(chuàng)建新的實例。在對內(nèi)容進行變更的時候,會開啟一塊新的內(nèi)存,偽代碼如下:這樣實現(xiàn)的目的:通過多份指針去引用同一份地址的成本遠遠低于開辟多份堆內(nèi)存。以下對比圖:支持ProtocolType的動態(tài)多態(tài)(DynamicPolymorphism)行為。通過使用WitnessTable和ExistentialContainer來實現(xiàn)。對于大數(shù)的拷貝可以通過IndirectStorage間接存儲來進行優(yōu)化。說到動態(tài)多態(tài)DynamicPolymorphism,我們就要問了,什么是靜態(tài)多態(tài)StaticPolymorphism,看看下面示例:這種情況我們就可以用到泛型Genericcode來實現(xiàn),進行進一步優(yōu)化。我們接下來會討論泛型屬性的存儲方式和泛型方法是如何分派的。泛型和ProtocolType的區(qū)別在于:泛型支持的是靜態(tài)多態(tài)。每個調(diào)用上下文只有一種類型。查看下面的示例,foo和bar方法是同一種類型。在調(diào)用鏈中會通過類型降級進行類型取代。對于以下示例:分析方法foo和bar的調(diào)用過程:泛型方法調(diào)用的具體實現(xiàn)為:同一種類型的任何實例,都共享同樣的實現(xiàn),即使用同一個ProtocolWitnessTable。使用Protocol/ValueWitnessTable。每個調(diào)用上下文只有一種類型:這里沒有使用ExistentialContainer,而是將Protocol/ValueWitnessTable作為調(diào)用方的額外參數(shù)進行傳遞。變量初始化和方法調(diào)用,都使用傳入的VWT和PWT來執(zhí)行??吹竭@里,我們并不覺得泛型比ProtocolType有什么更快的特性,泛型如何更快呢?靜態(tài)多態(tài)前提下可以進行進一步的優(yōu)化,稱為特定泛型優(yōu)化。靜態(tài)多態(tài):在調(diào)用站中只有一種類型Swift使用只有一種類型的特點,來進行類型降級取代。類型降級后,產(chǎn)生特定類型的方法為泛型的每個類型創(chuàng)造對應(yīng)的方法這時候你可能會問,那每一種類型都產(chǎn)生一個新的方法,代碼空間豈不爆炸?靜態(tài)多態(tài)下進行特定優(yōu)化specialization因為是靜態(tài)多態(tài)。所以可以進行很強大的優(yōu)化,比如進行內(nèi)聯(lián)實現(xiàn),并且通過獲取上下文來進行更進一步的優(yōu)化。從而降低方法數(shù)量。優(yōu)化后可以更精確和具體。例如:從普通的泛型展開如下,因為要支持所有類型的min方法,所以需要對泛型類型進行計算,包括初始化地址、內(nèi)存分配、生命周期管理等。除了對value的操作,還要對方法進行操作。這是一個非常的的工程。在確定入?yún)㈩愋蜁r,比如Int,編譯器可以通過泛型特化,進行類型取代(TypeSubstitute),優(yōu)化為:泛型特化specilization是何時發(fā)生的?在使用特定優(yōu)化時,調(diào)用方需要進行類型推斷,這里需要知曉類型的上下文,例如類型的定義和內(nèi)部方法實現(xiàn)。如果調(diào)用方和類型是單獨編譯的,就無法在調(diào)用方推斷類型的內(nèi)部實行,就無法使用特定優(yōu)化,保證這些代碼一起進行編譯,這里就用到了wholemoduleoptimization。而wholemoduleoptimization是對于調(diào)用方和被調(diào)用方的方法在不同文件時,對其進行泛型特化優(yōu)化的前提。特定泛型的進一步優(yōu)化:在用到多種泛型,且確定泛型類型不會在運行時修改時,就可以對成對泛型的使用進行進一步優(yōu)化。優(yōu)化的方式是將泛型的內(nèi)存分配由指針指定,變?yōu)閮?nèi)存內(nèi)聯(lián),不再有額外的堆初始化消耗。請注意,因為進行了存儲內(nèi)聯(lián),已經(jīng)確定了泛型特定類型的內(nèi)存分布,泛型的內(nèi)存內(nèi)聯(lián)不能存儲不同類型。所以再次強調(diào)此種優(yōu)化只適用于在運行時不會修改泛型類型,即不能同時支持一個方法中包含line和point兩種類型。wholemoduleoptimization是用于Swift編譯器的優(yōu)化機制??梢酝ㄟ^-whole-module-optimization(或-wmo)進行打開。在XCode8之后默認打開。SwiftPackageManager在release模式默認使用wholemoduleoptimization。module是多個文件集合。編譯器在對源文件進行語法分析之后,會對其進行優(yōu)化,生成機器碼并輸出目標文件,之后鏈接器聯(lián)合所有的目標文件生成共享庫或可執(zhí)行文件。wholemoduleoptimization通過跨函數(shù)優(yōu)化,可以進行內(nèi)聯(lián)等優(yōu)化操作,對于泛型,可以通過獲取類型的具體實現(xiàn)來進行推斷優(yōu)化,進行類型降級方法內(nèi)聯(lián),刪除多余方法等操作。全模塊優(yōu)化的優(yōu)勢編譯器掌握所有方法的實現(xiàn),可以進行內(nèi)聯(lián)和泛型特化等優(yōu)化,通過計算所有方法的引用,移除多余的引用計數(shù)操作。通過知曉所有的非公共方法,如果這寫方法沒有被使用,就可以對其進行消除。如何降低編譯時間和全模塊優(yōu)化相反的是文件優(yōu)化,即對單個文件進行編譯。這樣的好處在于可以并行執(zhí)行,并且對于沒有修改的文件不會再次編譯。缺點在于編譯器無法獲知全貌,無法進行深度優(yōu)化,全模塊優(yōu)化如何避免沒修改的文件再次編譯。編譯器內(nèi)部運行過程分為:語法分析,類型檢查,SIL優(yōu)化,LLVM后端處理。語法分析和類型檢查一般很快,SIL優(yōu)化執(zhí)行了重要的Swift特定優(yōu)化,例如泛型特化和方法內(nèi)聯(lián)等,該過程大概占用真?zhèn)€編譯時間的三分之一。LLVM后端執(zhí)行占用了大部分的編譯時間,用于運行降級優(yōu)化和生成代碼。進行全模塊優(yōu)化后,SIL優(yōu)化會將模塊再次拆分為多個部分,LLVM后端通過多線程對這些拆分模塊進行處理,對于沒有修改的部分,不會進行再處理。這樣就避免了修改一小部分,整個大模塊進行LLVM后端執(zhí)行,并且多線程并行操作也會縮短處理時間。Swift因為方法分派機制問題,所以在設(shè)計和優(yōu)化后,會產(chǎn)生和我們常規(guī)理解不太一致的結(jié)果,這當(dāng)然不能算Bug。但是還是要單獨進行說明,避免在開發(fā)過程中,因為對機制的掌握不足,造成預(yù)期和執(zhí)行出入導(dǎo)致的問題。Messagedispatch我們通過上面說明結(jié)合StaticdispatchVSDynamicdispatch對方法分派方式有了了解。這里需要對Objective-C的方法分派方式進行說明。熟悉OC的人都知道,OC采用了運行時機制使用obj_msgSend發(fā)送消息,runtime非常的靈活,我們不僅可以對方法調(diào)用采用swizzling,對于對象也可以通過isa-swizzling來擴展功能,應(yīng)用場景有我們常用的hook和大家熟知的KVO。大家在使用Swift進行開發(fā)時都會問,Swift是否可以使用OC的運行時和消息轉(zhuǎn)發(fā)機制呢?答案是可以。Swift可以通過關(guān)鍵字dynamic對方法進行標記,這樣就會告訴編譯器,此方法使用的是OC的運行時機制。注意:我們常見的關(guān)鍵字@ObjC并不會改變Swift原有的方法分派機制,關(guān)鍵字@ObjC的作用只是告訴編譯器,該段代碼對于OC可見。注意:我們常見的關(guān)鍵字@ObjC并不會改變Swift原有的方法分派機制,關(guān)鍵字@ObjC的作用只是告訴編譯器,該段代碼對于OC可見??偨Y(jié)來說,Swift通過dynamic關(guān)鍵字的擴展后,一共包含三種方法分派方式:Staticdispatch,Tabledispatch和Messagedispatch。下表為不同的數(shù)據(jù)結(jié)構(gòu)在不同情況下采取的分派方式:如果在開發(fā)過程中,錯誤的混合了這幾種分派方式,就可能出現(xiàn)Bug,以下我們對這些Bug進行分析:SR-584此情況是在子類的extension中重載父類方法時,出現(xiàn)和預(yù)期不同的行為。執(zhí)行以下代碼,直接調(diào)用沒有問題:間接調(diào)用結(jié)果和預(yù)期不同:在Base.directProperty前添加dynamic關(guān)鍵字就可以獲得"thisisSub"的結(jié)果。Swift在extension文檔中說明,不能在extension中重載已經(jīng)存在的方法?!癊xtensionscanaddnewfunctionalitytoatype,buttheycannotoverrideexistingfunctionality.”“Extensionscanaddnewfunctionalitytoatype,buttheycannotoverrideexistingfunctionality.”會出現(xiàn)警告:Cannotoverrideanon-dynamicclassdeclarationfromanextension。出現(xiàn)這個問題的原因是,NSObject的extension是使用的Messagedispatch,而InitialDeclaration使用的是Tabledispath(查看上圖SwiftDispatchMethod)。extension重載的方法添加在了Messagedispatch內(nèi),沒有修改虛函數(shù)表,虛函數(shù)表內(nèi)還是父類的方法,故會執(zhí)行父類方法。想在extension重載方法,需要標明dynamic來使用Messagedispatch。SR-103協(xié)議的擴展內(nèi)實現(xiàn)的方法,無法被遵守類的子類重載:現(xiàn)在定義一個遵守了協(xié)議的類Person。遵守協(xié)議類的子類LoudPerson:執(zhí)行下面代碼結(jié)果為:不符合預(yù)期的代碼:注意,在子類LoudPerson中沒有出現(xiàn)override關(guān)鍵字??梢岳斫鉃長oudPerson并沒有成功注冊Greetable在Witnesstable的方法。所以對于聲明為Person實際為LoudPerson的實例,會在編譯器通過Person去查找,Person沒有實現(xiàn)協(xié)議方法,則不產(chǎn)生Witnesstable,sayHi方法是直接調(diào)用的。解決辦法是在base類內(nèi)實現(xiàn)協(xié)議方法,無需實現(xiàn)也要提供默認方法?;蛘邔⒒悩擞洖閒inal來避免繼承。進一步通過示例去理解:其他我們知道Classextension使用的是Staticdispatch:以上代碼會出現(xiàn)錯誤,提示Declarationsinextensionsca

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論