作者: 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 inner class,C# Inner Class vs. java 的inner class比较-JSP教程,Java技巧及代码相关推荐

  1. java 工具箱安装方法,Java工具包的安装配置和使用-JSP教程,Java技巧及代码

    1.下载j2sdk 1.4.1或更高版本 (http://java.sun.com,建议同时下载其java documentation,这是java帮助文档) 2.运行刚刚下载的j2sdk-1_4_1 ...

  2. java程序获取外部java程序的控件,将 Java 小程序迁移到 Microsoft J# 浏览器控件-JSP教程,Java技巧及代码...

    visual j# .net 小组 microsoft corporation 摘要:通过 microsoft j# 浏览器控件,开发人员可以将所编写的在 java 虚拟机上运行的 java 小程序迁 ...

  3. java获取jsp 组件,利用Observer模式解决组件间通信问题-JSP教程,Java技巧及代码

    1. 问题的提出 以前做一个界面的时候常常会遇到这样的尴尬情况:希望保留各个独立的组件(类),但又希望它们之间能够相互通信.譬如windows中的explorer,我们希望鼠标点击左边是树型目录的一个 ...

  4. java代码写jsp读取,Java IO学习基础之读写文本文件-JSP教程,Java技巧及代码

    java的io操作都是基于流进行操作的,为了提高读写效率一般需要进行缓冲. 简单的示例程序如下: /** * 读出1.txt中的内容,写入2.txt中 * */ import java.io.*; p ...

  5. java线程池游戏代码,Java游戏起步:(一)线程与线程池-JSP教程,Java技巧及代码...

    任何游戏都至少需要运行两个线程,主线程和gui线程 而线程池是一个管理运行线程的有用工具,下面的代码示范了一个线程池的实现方法~~ ********************************** ...

  6. eclipse启动提示java,Eclipse启动时报错-JSP教程,Java技巧及代码

    前些日子下载了最新版本的eclipse3.0,解压到d:\eclipse目录下,启动时弹出一个小提示框说出错请查看eclipse\configuration\下的一个*******.log文件.文件中 ...

  7. 用java写四则混合运算,JAVA写的四则混合运算-JSP教程,Java技巧及代码

    这是一个四则混合运算程序,没什么做优化,也没做什么注释,(人啊,总喜欢偷懒的.) 这个版本我已经定为了2.21版本.呵呵. 从最先的1.0到2.0的改动很大.除了运算思想没动处,其它的都在2.0做了重 ...

  8. jsp里加java代码,利用静态内部类为您的代码添加辅助功能-JSP教程,Java技巧及代码...

    利用静态内部类为您的代码添加辅助功能 作者 john d. mitchell 摘要这个技巧提供了一个实例,它可以利用静态内部类为您的类添加独立的.可选的辅助功能,例如测试和示例代码等.( 500 字) ...

  9. java指定sql生成xml,用Java实现可保存状态的数据库生成XML树(8)-JSP教程,Java与XML...

    4.ejb-jar.xml文件 //sun microsystems, inc.//dtd enterprise javabeans 1.1//en http://java.sun.com/j2ee/ ...

最新文章

  1. 卷积神经网络——本质上是在利用卷积做特征压缩,然后再全连接
  2. js 检测input输入值是否全是汉字
  3. layui --- [结构优化]参数优化
  4. 制作程序化装饰花纹图案_装饰图案
  5. java 多线程 临界区_多线程编程的设计模式 临界区模式
  6. Java案例:装载与发射子弹问题
  7. java中的网络入门2(J2SE入门19)
  8. RT-Thread与cubemx|74HC595驱动数码管详解
  9. 状态机编程实例及适用范围
  10. CTS2019朝圣 x 打铁记
  11. Vue 移动端实现调用相机扫描二维码或条形码
  12. 牛客网:牛牛玩平板(c++)
  13. 关键词提取——有监督方法
  14. epublib java_java中使用Epublib解析EPub文件
  15. 飞书:远程办公更轻松
  16. 在CentOS下安装clickhouse
  17. 免费ARP(gratuitousARP)
  18. 个人形象设计之服装单品的理想搭配
  19. [软考]之原码、反码、补码和移码
  20. Caused by: org.xml.sax.SAXParseException;必须为元素类型 mapping 声明属性 resourse。

热门文章

  1. ICRA2021| 自动驾驶相关论文汇总
  2. 半个月3篇Nature/Science,95后曹原3年8篇顶刊,网友:杀疯了杀疯了
  3. SLAM综述|激光与视觉融合SLAM
  4. linux可以远程装机吗,linux 远程装机
  5. 读“深度学习在图像处理领域中的应用综述”有感
  6. 报表统计-mysql存储过程
  7. 在线作图|2分钟绘制一张箱线图
  8. ggplot2笔记3:工具箱——误差线、加权数、展示数据分布
  9. 宏基因组实战10. 绘制圈图-Circos安装与使用
  10. ValueError: cannot convert to ‘int64‘-dtype NumPy array with missing values. Specify an appropriate