快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

C# Inner Class vs. java 的inner class比较

作者: leafwiz www.ASPCool.com 时间:2004-11-6 15:50:57 阅读次数:1811




今天朋友问到,为什么在C#中inner class不能够访问外部类的非静态成员,如下面的一段代码就存在这样的问题:

public class TestOuter

{

public static void outer(){}

public void outer2(){}



internal class A

{

public voidtest()

{

outer(); // 可以调用外部静态方式,无法调用实例方式

outer2(); // 本句无法通过编译

}

}

}

在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();

}

}

}



对比之下,C#中的内部类能够使用外部类定义的类型和静态方式,但是不能直接使用外部类的实例方式,直接看来,外部类对于内部类的作用更像是一个命名空间,在C#中,始终可以用(只要访问控制答应)

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

来创建一个内部类的实例,这个实例与外部类的任何实例没有任何直接的关系。类似于Java中的静态内部类。

Java中,非静态内部类可以访问所有外部类的方式和变量。所以Java中的内部类的构造也依靠于外部类,必须使用如:

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

这样的语法来定义内部类的实例以确保他与某一确定的外部类的对象相对应。

而在C#中,类区分为Nested Class和Not-Nested Class,前者是声明在其他数据类型内部的类。后者是直接定义在某一个命名空间的类。

非内嵌类只答应使用public和internal的访问控制,而内置类则答应使用所有的五种访问控制符,private, protected , internal protected。内部类也可以访问外部类的所有方式,包括instance方式和private方式,但是需要显式的传递一个外部类的实例。

如:

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 这样的语法,保持一致的对象创建方法。虽然相比于Java需要创建一个新的方式和变量,但是对象的创建过程更加直接,而且避免了隐含的内部类与外部类的实例之间的关系。

假如分析到CLR的实现层面,我们也可以知道,C#的内部类应该并没有包含外部类的虚函数表,而仅仅包含了静态方式表,所有对外部类的方式的调用时通过外部类指针作的。详细的机制可能更复杂。但是除此以外,内部类并没有被作为一种特别的类型处理,而是必须与其他普通的对象采取相同的机制进行创建。

C#的内部类提供了覆盖的功能,在一个包含了内部类的类的子类中可以用要害字new 来覆盖同名内部类的实现。

如:

class A1

{

class B1 { }

}

class A2 : A1

{

new class B1 { }

}

C#中的内部类会覆盖同名的外部类的方式。假如上面的A1中定义任何名为B1()的方式,该方式将被覆盖。



内部类使用的一些General Information:

创建内部类的一个目的是为了抽象外部类的某一状态下的行为,或者内部类仅在外部类的某一特定上下文存在。或是隐藏实现,通过将内部类设为private,可以设置仅有外部类可以访问该类。内部类的另外一个重要的用途是当外部类需要作为某个特定的类工作,而外部类已经继续与另外一个类的时候,因为Java不支持多继续,所以创建一个对应的内部类作为外部类的一个façade来使用。

通常,创建内部类的动机都是上面中的其中之一或者几项。而其中最常见的目的莫过于前两项。

我们看一下Java中处理事件的代码:

public class Demo1 extends JPanel

{

class IconDemo implements Icon {}

}

这个例子对应了上面的第一种动机,即封装特定状态或特定实现的动机。IconDemo仅在的Demo1中使用,对应特定的图标绘制行为。

常见的另外一个场合是需要自定义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可以看成是一种特化的要求。



隐藏实现的需求往往对应于内部抽象,或者二次抽象(Secondary Abstraction),它对应着对于类内部的部分行为进一步抽象,聚簇。常见的一种情况是在内部类中创建私有的结构,用于抽象尽在类的内部使用的数据结构。



而作为Façade使用的情况相称于外部类作为内部类的创建工厂,当外部哀求需要外部类提供一个它不能够继续的基类或接口的时候,外部类产生一个内部类的实例对象,返回给相应的哀求。



创建内部类的一些原则:

假如一下一些情况出现,避免使用内部类:

内部类的功能过分膨胀影响了对外部类的阅读

内部类内部包含内部类,对代码的可读性影响很大

内部类可以不依靠于外部类被使用,在这种情况下,说明内部类与外部类的抽象没有包含关系,则应该将内部类作为一种独立的抽象设计为另外一个外部类。(可以参考内部类设计的第二目的,内部抽象)



注:在VC中可以使用内部类作为模版的局部特化处理,擦过不提。其实我也不太懂,:)







返回类别: 教程
上一教程: 《java与模式》----创建模式系列工厂模式、单态模式精讲
下一教程: Remote scripting using a servlet

您可以阅读与"C# Inner Class vs. java 的inner class比较"相关的教程:
· Java Inner Class
· Java编程极限考验:ClassLoader类装载策略
· 回答:为什么执行JAVA程序时,会出现Exception in thread"main" java.lang.NoClassDefFoundError的错?...
· 《Java编程思想》(第二版)第6:重复运用classes
· Java中new DerivedClass()时背后发生的事情
    微笑服务 优质保证 索取样品