靈魂-放水

          為學(xué)日益,為道日損。

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            296 Posts :: 10 Stories :: 274 Comments :: 0 Trackbacks
          為什么在C#中inner class不能夠訪問(wèn)外部類的非靜態(tài)成員,如下面的一段代碼就存在這樣的問(wèn)題:

          public class TestOuter

          {

          public static void outer(){}

          public void outer2(){}



          internal class A

          {

          public voidtest()

          {

          outer(); // 可以調(diào)用外部靜態(tài)方法,無(wú)法調(diào)用實(shí)例方法

          outer2(); // 本句無(wú)法通過(guò)編譯

          }

          }

          }

          在Java中,下面的代碼是可以很正常的使用的:

          public class testinner

          {

          static public void Main(String[] args)

          {

          testinner tester = new testinner();

          testinner.Inner inner = tester.new Inner();

          inner.testinner();

          }

          public void test(){ }



          class Inner

          {

          public void testinner()

          {

          test();

          }

          }

          }



          對(duì)比之下,C#中的內(nèi)部類能夠使用外部類定義的類型和靜態(tài)方法,但是不能直接使用外部類的實(shí)例方法,直接看來(lái),外部類對(duì)于內(nèi)部類的作用更像是一個(gè)命名空間,在C#中,始終可以用(只要訪問(wèn)控制允許)

          TestOuter.A instance = new TestOuter.A();

          來(lái)創(chuàng)建一個(gè)內(nèi)部類的實(shí)例,這個(gè)實(shí)例與外部類的任何實(shí)例沒(méi)有任何直接的關(guān)系。類似于Java中的靜態(tài)內(nèi)部類。

          Java中,非靜態(tài)內(nèi)部類可以訪問(wèn)所有外部類的方法和變量。所以Java中的內(nèi)部類的構(gòu)造也依賴于外部類,必須使用如:

          Outer.Inner inner = outer.new Inner();

          這樣的語(yǔ)法來(lái)定義內(nèi)部類的實(shí)例以確保他與某一確定的外部類的對(duì)象相對(duì)應(yīng)。

          而在C#中,類區(qū)分為Nested Class和Not-Nested Class,前者是聲明在其他數(shù)據(jù)類型內(nèi)部的類。后者是直接定義在某一個(gè)命名空間的類。

          非內(nèi)嵌類只允許使用public和internal的訪問(wèn)控制,而內(nèi)置類則允許使用所有的五種訪問(wèn)控制符,private, protected , internal protected。內(nèi)部類也可以訪問(wèn)外部類的所有方法,包括instance方法和private方法,但是需要顯式的傳遞一個(gè)外部類的實(shí)例。

          如:

          public class TestOuter

          {

          public void outer2(){}



          internal class A

          {

          public A(TestOuter obj)

          {

          Outer_this = obj

          }

          public void test()

          {

          obj.outer2();

          }

          TestOuter Outer_this;

          }

          }

          C#這樣做的原因,主要是為了避免outer.new 這樣的語(yǔ)法,保持一致的對(duì)象創(chuàng)建方式。雖然相比于Java需要?jiǎng)?chuàng)建一個(gè)新的方法和變量,但是對(duì)象的創(chuàng)建過(guò)程更加直接,而且避免了隱含的內(nèi)部類與外部類的實(shí)例之間的關(guān)系。

          如果分析到CLR的實(shí)現(xiàn)層面,我們也可以知道,C#的內(nèi)部類應(yīng)該并沒(méi)有包含外部類的虛函數(shù)表,而僅僅包含了靜態(tài)方法表,所有對(duì)外部類的方法的調(diào)用時(shí)通過(guò)外部類指針作的。具體的機(jī)制可能更復(fù)雜。但是除此以外,內(nèi)部類并沒(méi)有被作為一種特殊的類型處理,而是必須與其他普通的對(duì)象采取一樣的機(jī)制進(jìn)行創(chuàng)建。

          C#的內(nèi)部類提供了覆蓋的功能,在一個(gè)包含了內(nèi)部類的類的子類中可以用關(guān)鍵字new 來(lái)覆蓋同名內(nèi)部類的實(shí)現(xiàn)。

          如:

          class A1

          {

          class B1 { }

          }

          class A2 : A1

          {

          new class B1 { }

          }

          C#中的內(nèi)部類會(huì)覆蓋同名的外部類的方法。如果上面的A1中定義任何名為B1()的方法,該方法將被覆蓋。



          內(nèi)部類使用的一些General Information:

          創(chuàng)建內(nèi)部類的一個(gè)目的是為了抽象外部類的某一狀態(tài)下的行為,或者內(nèi)部類僅在外部類的某一特定上下文存在。或是隱藏實(shí)現(xiàn),通過(guò)將內(nèi)部類設(shè)為private,可以設(shè)置僅有外部類可以訪問(wèn)該類。內(nèi)部類的另外一個(gè)重要的用途是當(dāng)外部類需要作為某個(gè)特定的類工作,而外部類已經(jīng)繼承與另外一個(gè)類的時(shí)候,因?yàn)镴ava不支持多繼承,所以創(chuàng)建一個(gè)對(duì)應(yīng)的內(nèi)部類作為外部類的一個(gè)façade來(lái)使用。

          通常,創(chuàng)建內(nèi)部類的動(dòng)機(jī)都是上面中的其中之一或者幾項(xiàng)。而其中最常見(jiàn)的目的莫過(guò)于前兩項(xiàng)。

          我們看一下Java中處理事件的代碼:

          public class Demo1 extends JPanel

          {

          class IconDemo implements Icon {}

          }

          這個(gè)例子對(duì)應(yīng)了上面的第一種動(dòng)機(jī),即封裝特定狀態(tài)或特定實(shí)現(xiàn)的動(dòng)機(jī)。IconDemo僅在的Demo1中使用,對(duì)應(yīng)特定的圖標(biāo)繪制行為。

          常見(jiàn)的另外一個(gè)場(chǎng)合是需要自定義Action的行為,我們可能有如下的類:

          public class Demo1 extends JPanel implements ActionListener

          {

          private JMenuItem item1;

          void foo()

          {

          Item1 = new JMenuItem(“test” , new TestAction(“some action”));

          }

          Private TestAction extends AbstractAction

          {

          //code goes here

          }

          }

          這種情況下,TestAction可以看成是一種特化的要求。



          隱藏實(shí)現(xiàn)的需求往往對(duì)應(yīng)于內(nèi)部抽象,或者二次抽象(Secondary Abstraction),它對(duì)應(yīng)著對(duì)于類內(nèi)部的部分行為進(jìn)一步抽象,聚簇。常見(jiàn)的一種情況是在內(nèi)部類中創(chuàng)建私有的結(jié)構(gòu),用于抽象盡在類的內(nèi)部使用的數(shù)據(jù)結(jié)構(gòu)。



          而作為Façade使用的情況相當(dāng)于外部類作為內(nèi)部類的創(chuàng)建工廠,當(dāng)外部請(qǐng)求需要外部類提供一個(gè)它不能夠繼承的基類或接口的時(shí)候,外部類產(chǎn)生一個(gè)內(nèi)部類的實(shí)例對(duì)象,返回給相應(yīng)的請(qǐng)求。



          創(chuàng)建內(nèi)部類的一些原則:

          如果一下一些情況出現(xiàn),避免使用內(nèi)部類:

          內(nèi)部類的功能過(guò)分膨脹影響了對(duì)外部類的閱讀

          內(nèi)部類內(nèi)部包含內(nèi)部類,對(duì)代碼的可讀性影響很大

          內(nèi)部類可以不依賴于外部類被使用,在這種情況下,說(shuō)明內(nèi)部類與外部類的抽象沒(méi)有包含關(guān)系,則應(yīng)該將內(nèi)部類作為一種獨(dú)立的抽象設(shè)計(jì)為另外一個(gè)外部類。(可以參考內(nèi)部類設(shè)計(jì)的第二目的,內(nèi)部抽象)



          注:在VC中可以使用內(nèi)部類作為模版的局部特化處理,掠過(guò)不提。其實(shí)我也不太懂,:)
          posted on 2007-02-01 13:48 放水老倌 閱讀(418) 評(píng)論(0)  編輯  收藏 所屬分類: .NET
          主站蜘蛛池模板: 镇平县| 岐山县| 大港区| 敦化市| 利辛县| 塔河县| 黎川县| 沈丘县| 广东省| 亚东县| 乐东| 宁蒗| 兴安盟| 新乐市| 贵南县| 鄂托克前旗| 卓资县| 鄂伦春自治旗| 巩留县| 比如县| 聂荣县| 兴国县| 滦南县| 那坡县| 光山县| 西青区| 宁明县| 浑源县| 淮阳县| 香港 | 亚东县| 教育| 常德市| 平陆县| 定陶县| 富蕴县| 枣强县| 保德县| 卢湾区| 无锡市| 休宁县|