《JAVA编程思想》学习备忘(p345 Inner Classes-2)

续《JAVA编程思想》学习备忘(p345 Inner Classes-1)

Factory Method revisited

Look at how much nicer the interfaces/Factories.java example comes out when you use anonymous inner classes:

interface Service {
 void method1();
 void method2();
}

interface ServiceFactory{
 Service getService();
}

class Implementation1 implements Service{
 private Implementation1(){}
 public void method1() {
  System.out.println("Implementation1 method1");
 }
 public void method2() {
  System.out.println("Implementation1 method2");
 }
 public static ServiceFactory factory = new ServiceFactory(){
  public Service getService() {
   return new Implementation1();
  }
  
 };
}

class Implementation2 implements Service{
 private Implementation2(){}
 public void method1() {
  System.out.println("Implementation2 method1");
 }
 public void method2() {
  System.out.println("Implementation2 method2");
 }
 public static ServiceFactory factory=new ServiceFactory(){
  public Service getService() {
   return new Implementation2();
  }
 };
}
public class Factories {
 public static void serviceConsumer(ServiceFactory fact){
  Service s = fact.getService();
  s.method1();
  s.method2();
 }
 public static void main(String[] args) {
  serviceConsumer(Implementation1.factory);
  //Implementations are completely interchangeable:
  serviceConsumer(Implementation2.factory);
 }
}

输出:

Implementation1 method1
Implementation1 method2
Implementation2 method1
Implementation2 method2

Now the constructors for Implementation1 and Implementation2 can be private,and there's no need to create a named class as the factory.In addition,you often only need a single factory object,and so here it has been created as a static field in the Service implementation.The resulting syntax is more meaningful,as well.

 

The interfaces/Games.java example can also be improved with anonymous inner classes:

interface Game {
 boolean move();
}

interface GameFactory{
 Game getGame();
}

class Checkers implements Game{
 private Checkers(){}
 private int moves = 0;
 private static final int MOVES = 3;
 public boolean move() {
  System.out.println("Checkers move " + moves);
  return ++moves != MOVES;
 }
 public static GameFactory factory = new GameFactory(){
  public Game getGame() {
   return new Checkers();
  }
 };
}

class Chess implements Game{
 private Chess(){}
 private int moves = 0;
 private static final int MOVES = 4;
 public boolean move() {
  System.out.println("Chess move " + moves);
  return ++moves != MOVES;
 }
 public static GameFactory factory = new GameFactory(){
  public Game getGame() {
   return new Chess();
  }
 };
}

public class Games {
 public static void playGame(GameFactory factory){
  Game s = factory.getGame();
  while(s.move());
 }
 public static void main(String[] args) {
  playGame(Checkers.factory);
  playGame(Chess.factory);
 }
}

输出:

Checkers move 0
Checkers move 1
Checkers move 2
Chess move 0
Chess move 1
Chess move 2
Chess move 3

Nested classes

If you don't need a connection between the inner-class object and the outer-class object,then you can make the inner class static.This is commonly called a nested class.

...A nested class means:

1.You don't need an outer-class object in order to create an object of a nested class.

2.You can't access a non-static outer-class object from an object of a nested class.

...nested classes can have all of these:

public class Parcel11 {
 private static class ParcelContents implements Contents{
  private int i = 11;
  public int value() {
   return i;
  }
 }
 protected static class ParcelDestination implements Destination{
  private String label;
  private ParcelDestination(String whereTo){
   label = whereTo;
  }
  public String readLabel() {
   return label;
  }
  // Nested classes can contain other static elements:
  public static void f(){}
  static int x = 10;
  static class AnotherLevel{
   public static void f(){}
   static int x = 10;
  }
 }
 public static Destination destination(String s){
  return new ParcelDestination(s);
 }
 public static Contents contents(){
  return new ParcelContents();
 }
 public static void main(String[] args) {
  Contents c = contents();
  Destination d = destination("Tasmania");
 }
}

 

Classes inside interfaces

示例:

public interface ClassInInterface {
 void howdy();
 class Test implements ClassInInterface{
  public void howdy() {
   System.out.println("Howdy!");
  }
  public static void main(String[] args){
   new Test().howdy();
  }
 }
}

输出:

Howdy!

It's convenient to nest a class inside an interface when you want to create some common code to be used with all different implementations of that interface.

示例:

public class TestBed {
 public void f(){
  System.out.println("f()");
 }
 public static class Tester{
  public static void main(String[] args){
   TestBed t = new TestBed();
   t.f();
  }
 }
}

输出:

f()

 

Reaching outward from a  multiply nested class

it doesn't matter how deeply an inner class may be nested-it can transparently access all of the members of all the classes it nested within,as seen here:

class MNA {
 private void f(){}
 class A{
  private void g(){}
  public class B{
   void h(){
    g();
    f();
   }
  }
 }
}

public class MultiNestingAccess {
 public static void main(String[] args) {
  MNA mna = new MNA();
  MNA.A mnaa = mna.new A();
  MNA.A.B mnaab = mnaa.new B();
  mnaab.h();
 }
}

You can see that in MNA.A.B,the methods g() and f() are callable without any qualification(despite the fact that they are private).This example also demonstrates the syntax necessary to create objects of multiply nested inner classes when you create the objects in a diffrent class.The ".new"syntax produces the correct scope,so you do not have to qualify the class name in the constructor call.

 

Why inner classes?

...Typically,the inner class inherits from a class or implements an interface,and the code in the inner class manipulates the outer-class object that it was created within.So you could say that an inner class provides a kind of window into the outer class.

...So what is it that distinguishes an inner class implementing an interface from an outer class implementing the same interface?The answer is that you can't always have the convenience of interfaces-sometimes you're working with implementations.So the most compelling reason for inner classes is:

Each inner class can independently inherit from an implementation.Thus,the inner class is not limited by whether the outer class is already inheriting from an implementation.

...So one way to look at the inner class is as the rest of the solution of the multiple-inheritance problem.Interfaces solve part of the problem,but inner classes effectively allow"multiple implementation inheritance."That is,inner classes effectively allow you to inherit from more than one non-interface.

public interface A {}

public interface B {}

public class X implements A,B{}

public class Y implements A {
 B makeB(){
  return new B(){};
 }
}

public class MultiInterfaces {
 static void takesA(A a){}
 static void takesB(B b){}
 public static void main(String[] args) {
  X x = new X();
  Y y = new Y();
  takesA(x);
  takesA(y);
  takesB(x);
  takesB(y.makeB());
 }
}

 

However,if you have abstract or concrete classes instead of interfaces,you are suddenly limited to using inner classes if your class must somehow implement both of the others:

class D {}

abstract class E{}

class Z extends D{
 E makeE(){return new E(){};}
}

public class MultiImplementation {
 static void takesD(D d){}
 static void takesE(E e){}
 public static void main(String[] args) {
  Z z = new Z();
  takesD(z);
  takesE(z.makeE());
 }
}

 

...with inner classes you have these additional features:

1.The inner class can have multiple instances,each with its own state information that is independent of the information in the outer-class object.

2.In a single outer class you can have several inner classes,each of which implements the same interface or inherites from the same class in a different way.An example of this will be shown shortly.

3.The point of creation of the inner-class object is not tied to the creation of the outer-class object.

4.There is no potentially confusing "is-a" relationship with the inner class;it's a separate entity.

(待续)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值