浏览 1629 次
锁定老帖子 主题:对JAVA内部类的初步研究
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-03-18
public class Parent { protected String p ="p"; //这里的P不能为private,必须为protected或public,不然c无法调用 至于为什么,自己想想吧。 protected boolean p() { return true; } } public class A extends Parent { private String a = "a"; private boolean a() { return true; } public class B extends A { private String b = "b"; private boolean b() { return true; } public void vistorAllParentClass(){ System.out.println("b:"+b); System.out.println("a:"+a); System.out.println("p:"+p); System.out.println("b():"+b()); System.out.println("a():"+a()); System.out.println("p():"+p()); } } } public class Test { public static void main(String[] a){ A.B b = new A().new B(); //注意 非静态内部类必须依赖于外围类的对象才能创建,所以有以上语法。 b.vistorAllParentClass(); } } 可以看出上述代码 实现了 b这个内部类能同时访问父类A,以及A的父类Parent属性极其方法, 这就间接的实现C++中的多重继承特性 同时比继承更进一步,能访问父类的PRIVATE属性及其方法!!!! 仔细看上面的代码,会发现 A.B b = new A().new B(); 这种编码方式有股坏味道。 因为如果没有研究过A类的代码,将无法了解A的继承体系,从而无法得知B, 同时将作为内部类B设置为PUBLIC暴露出A类的大量内部细节,也不是什么好的设计。 如何解决这种粗糙的编码方式呢? 这就涉及到接口了,定义一个 接口: public interface Vistor{ void vistorAllParentInfo(); } 然后 将A的代码改成: public class A extends Parent { private String a = "a"; private boolean a() { return true; } private class B extends A implements Vistor{ private String b = "b"; private boolean b() { return true; } public void vistorAllParentInfo(){ System.out.println("b:"+b); System.out.println("a:"+a); System.out.println("p:"+p); System.out.println("b():"+b()); System.out.println("a():"+a()); System.out.println("p():"+p()); } } public Vistor getVistor(){ return new A().new B(); } } 然后 将Test的代码改成: public class Test { public static void main(String[] args){ A a = new A(); Vistor vistor = a.getVistor(); vistor.vistorAllParentInfo(); } } 此时就能通过 Vistor vistor = a.getVistor(); 将实现了多重继承,携带了所有父类内部细节的B类以接口形式暴露出部分行为。 这种方式带来的好处出来便于使用B类,同时也体现了面向对象中的封装性,使用安全的接口操作对象的属性和行为,而无需知道实际对象的内部细节。 注意看 A中B类的访问权限是private,而Vistor是public,并且Test能捕获转型后的B类,即B的接口方法作为PUBLIC抛到了外围类。 这一点将"接口行为与具体类的实现无关"这一继承特性 体现的淋漓尽致!!! 让我们再来看看内部类是如何化解继承中"is a"的困惑的。 在编程时,我们有时会遇到这种困境: //行为 public interface Behavior{ void addItem(String data); void delItem(int i); }; //数据 public class DataSource{ private List dataList = new ArrayList(); } public class Deal{ public static void main(String[] a){ //下面我们要使用Behavior的接口来操作dataSource。 该如何办呢? } } 上面Deal提出的疑问我们该如何解决呢?Behavior并没有提供方法可以获取一个dataSource的应用。 简单考虑有两种方法能解决上述问题: 1 定义一个Behavior具体类BehaviorImpl 并加入方法setDataSource(DataSource data);然后操作。 2 将DataSource继承Behavior,然后重载接口行为。 来看看两种方式缺点: 首先方法1 将导致创建新类,同时Behavior的实现必须和Deal的main方法实现耦合在一起,并且暴露了Behavior与DataSource关联的细节。 因为只有在Deal的main中使用behaviorImpl.setDataSource(data);的形式来使方法1成立。 然后是方法2 DataSource继承Behavior 将导致"is a"的困惑出现:DataSource究竟是一个数据源对象还是一个行为对象呢? 这模糊DataSource对象的语义。 如果使用内部类就能解决上述问题了~~~~~~ 改造下DataSource public class DataSource{ private List dataList = new ArrayList(); public Behavior getBehavior(){ return new Behavior(){ public void addItem(String data){ dataList.add(data); } public void delItem(int i){ dataList.remove(i); } }; } } public class Deal{ public static void main(String[] a){ DataSource d = new DataSource(); Behavior b = d.getBehavior(); b.addItem("12121"; b.delItem(0); } } 这样就将具体DataSource对象的具体行为封装到DataSource中了,避免了添加新类,同时也封装了DataSource 与 Behavior的关联实现。 并且达到对象语义上的清晰-------"DataSource对象是一个数据源,并带有一个在其数据上进行操作的具体行为对象Behavior" 至于内部类对回调的支持,主要也是通过接口和匿名内部类实现,方式与上面的差不多,不说也罢。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |