对JAVA内部类的初步研究

昨天看了THANKING JAVA中的内部类,结合自己的经历,在这里做个小节,算是读后感吧
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"

至于内部类对回调的支持,主要也是通过接口和匿名内部类实现,方式与上面的差不多,不说也罢。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值