免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1405 | 回复: 0
打印 上一主题 下一主题

Inner Class 嵌套式类 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-03-18 14:23 |只看该作者 |倒序浏览
什么是嵌套式类?
顾名思义,Java 语言中的嵌套式类 是在另一个类中声明的类。以下是一个简单的例子:
public class EnclosingClass {
        ...
        public class NestedClass {
        ...
        }
}
什么是嵌套式类?
顾名思义,Java 语言中的嵌套式类 是在另一个类中声明的类。以下是一个简单的例子:
public class EnclosingClass {
        ...
        public class NestedClass {
        ...
        }
}
通常,好的编程人员会在嵌套式类只在封闭类的上下文中有意义的时候定义嵌套式类。常见的一些例子如下所示:
  • UI 类中的事件处理程序。
  • 用于组件中的那些 UI 组件的辅助类。
  • 适配器类,将某一个类的内部结构转换成其他一些用于该类的用户的形式。

可以将嵌套式类定义为 public、private 或 protected。还可以将嵌套式类定义为 final(以便保护它,使它免受更改)、abstract(意味着它不能被继承)或 static。
当在另一个类中创建 static 类时,将相应地创建一个称为嵌套式类的类。嵌套式类是在另一个类中定义的,但它可以存在于封闭类的实例之外。如果嵌套式类不是 static,那么它只能存在于封闭类的实例中,并且它有一个更适当的称呼,称为内部类。换句话说,所有内部类都是嵌套式类,但并不是所有的嵌套式类都是内部类。在您的工作中遇到的大多数嵌套式类都将是内部类,而不是只是嵌套式类。
任何嵌套式类都可以访问封闭类的所有成员,即使没有将它们声明为 private 也是如此。
 
定义嵌套式类
定义嵌套式类就像定义非嵌套式类那样,但这项操作是在封闭类中完成的。举一个稍微有点假的例子:在 Adult 内部定义一个 Wallet 类。尽管除了 Adult 之外,实际上还可以拥有一个 Wallet 类,但它并不总是一直有用,所以让每个 Adult 拥有一个 Wallet(或者至少有一个地方存放钱,MoneyContainer 听起来有点怪)是很有道理的。Wallet 并没有存在于 Person 之上也是有一定道理的,因为 Baby 不需要用钱包,如果 Person 上存在 Wallet,那么 Person 的所有子类都将继承它。
这里的 Wallet 将非常简单,因为只有服务器说明了嵌套式类的定义:
protected class Wallet {
        protected ArrayList bills = new ArrayList();
       
        protected void addBill(int aBill) {
                bills.add(new Integer(aBill));
        }
       
        protected int getMoneyTotal() {
                int total = 0;
                for (Iterator i = bills.iterator(); i.hasNext(); ) {
                        Integer wrappedBill = (Integer) i.next();
                        int bill = wrappedBill.intValue();
                        total += bill;
                }
                return total;
        }
}
我们将定义 Adult 中的类,如下所示:
public class Adult extends Person {
        protected Wallet wallet = new Wallet();
        public Adult() {
        }
        public void talk() {
                System.out.println("Spoke.");
        }
        public void acceptMoney(int aBill) {
                this.wallet.addBill(aBill);
        }
        public int moneyTotal() {
                return this.wallet.getMoneyTotal();
        }
        protected class Wallet {
                ...
        }
}
注意,我们添加了 acceptMoney() 来允许 Adult 接受更多的钱。(也可以随意地扩展这个例子,强迫 Adult 给出一些钱,这在现实生活中是很常见的事。)
一旦拥有了自己的嵌套式类和新的 acceptMoney() 方法,就可以使用它们,如下所示:
Adult anAdult = new Adult();
anAdult.acceptMoney(5);
System.out.println("I have this much money: " + anAdult.moneyTotal());
执行以下代码应该报告说 anAdult 的总钱数为 5。
 
过分简单事件的处理
Java
语言定义了一个事件处理方法,该方法包含相关的类,它允许您创建和处理自己的事件。但事件处理可能比这更简单。实际上,所有您需要的只是一些生成“事件”
的逻辑(该逻辑事实上根本不必是事件类),以及监听该事件并随后相应地给出响应的逻辑。例如,假设无论何时移动 Person,系统都会生成(或者激活)一个 MoveEvent,我们可以选择是处理这个事件,还是不处理这个事件。这要求对系统做一些更改。必须进行以下操作:
  • 创建一个“应用程序”类来启动系统,并使用匿名内部类进行说明。
  • 创建一个应用程序可以实现的 MotionListener,然后在监听器中处理事件。
  • 添加一个监听器的 List 到 Adult 中。
  • 添加一个 addMotionListener() 方法到 Adult 中,以便注册一个监听器。
  • 添加一个 fireMoveEvent() 方法到 Adult中,这样就可以告诉监听器何时处理事件。
  • 添加代码到应用程序中,以便创建一个 Adult 并将其注册为处理程序。

所有这些都很简单。以下是包含新的材料的 Adult:
public class Adult extends Person {
        protected Wallet wallet = new Wallet();
        protected ArrayList listeners = new ArrayList();
        public Adult() {
        }
        public void move() {
                super.move(); fireMoveEvent();
        }
        ...
        public void addMotionListener(MotionListener aListener) {
                listeners.add(aListener);
        }
        protected void fireMoveEvent() {
                Iterator iterator = listeners.iterator();
                while(iterator.hasNext()) {
                        MotionListener listener = (MotionListener) iterator.next();
                        listener.handleMove(this);
                }
        }
        protected class Wallet {
                ...
        }
}
注意,我们现在要重写 move(),先调用 Person 上的 move(),然后调用 fireMoveEvent() 告诉监听器作出响应。我们还添加了一个 addMotionListener(),以便将 MotionListener 添加到监听器的运行列表中。以下是一个 MotionListener:
public interface MotionListener {
        public void handleMove(Adult eventSource);
}
所有剩下要做的事就是创建应用程序类:
public class CommunityApplication implements MotionListener {
        public void handleMove(Adult eventSource) {
                System.out.println("This Adult moved:
" + eventSource.toString());
        }
        public static void main(String[] args) {
                CommunityApplication application = new CommunityApplication();
                Adult anAdult = new Adult();
                anAdult.addMotionListener(application);
                anAdult.move();
        }
}
这个类实现了 MotionListener 接口,这意味着它实现了 handleMove()。在这里,我们要做的所有事情就是输出一条消息,以说明事件是何时激发的。
 
匿名内部类
匿名 内部类允许在适当的位置定义一个类,而不用命名这个类,以便提供一些特定于上下文的行为。在用户界面中,这是一种用于处理程序的常见方法,这个主题超出了本教程的讨论范围。我们甚至可以在过于简单的事件处理示例中使用匿名内部类。
通过更改对 CommunityApplication.main() 中 addMotionListener() 的调用,可以将前面使用的例子转换成使用匿名内部类,如下所示:
anAdult.addMotionListener(new MotionListener() {
        public void handleMove(Adult eventSource) {
                System.out.println("This Adult moved:
" + eventSource.toString());
        }
});
我们宁愿让 CommunityApplication 实现 MotionListener,也不愿意声明类型 MotionListener 的未指定(因而匿名)的内部类,并为它提供 handleMove() 的实现。事实上,MotionListener 是一个接口,而不是一个类,但是没关系,无论哪种情况都可以接受。
这个代码产生的结果与前面版本产生的结果完全相同,但它使用了一个更常见的并且人们期望使用的方法。几乎总是可以看见用匿名内部类实现的事件处理程序。
 
使用嵌套式类
嵌套式类可能非常有用,但它们也可能会带来一些痛苦。
当在封闭类之外定义类不那么合理的时候,可以使用嵌套式类。在这个例子中,我们可以拥有在 Adult 之外定义的 Wallet,感觉不错。但是,请设想一下 Personality 这样的类。您曾经有一个位于 Person 实例之外的类吗?没有吧,所以,将这个类定义为嵌套式类是很合理的。一条好的经验法则是:除非显然应该将类定义为嵌套式类,然后重构这个类来实现其嵌套,否则应该将该类定义为非嵌套式类。

名内部类是用于事件处理程序的标准方法,因此,可以将它们用于这些方面。在其他情况下,要小心使用它们。除非匿名内部类很小、很集中并且是人们惯用的,否
则这些类会弄乱代码。它们还会使调试更加困难,虽然 Eclipse IDE
有助于减轻这种痛苦。通常,除了对事件处理程序使用匿名内部类,绝对不要尝试在其他情况下使用匿名内部类。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/5142/showart_16341.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP