为什么需要内部类

1. 可以实现多继承

    我们知道,java中的类目前只支持单继承,即类只能有个直接父类。但如果我们想要继承两个抽象类,此时需要借助内部类实现。

    如:

abstract class FlyingAnimal {
	abstract void fly();
}

abstract class SwimmingAnimal {
	abstract void swim();
}

/**
 * Swan(天鹅)类既继承抽象类FlyingAnimal(飞行动物),又要继承SwimmingAnimal(游动物)
 * @author zhoua
 *
 */
public class Swan extends FlyingAnimal{

	@Override
	void fly() {
		// TODO Auto-generated method stub
		System.out.println("Swan.fly()");
	}
	
	void swim() {
		this.getSwimming().swim();
	}
	
	SwimmingAnimal getSwimming() {
		return new SwimmingAnimal(){

			@Override
			void swim() {
				// TODO Auto-generated method stub
				System.out.println("Swan.swim()");
			}
			
		};
	}
	
	
	public static void main(String[] args) {
		Swan swan = new Swan();
		swan.fly();
		swan.swim();
	}
}

在此例中,

Swan(天鹅)类既继承抽象类FlyingAnimal(飞行动物),又要继承SwimmingAnimal(游动物)。但Swan只能继承一个类FlyingAnimal,另一个类的继承与方法复写,只能在内部类中继承实现。所以在内部类中,通过getSwimming()方法,返回一个匿名内部类实例,并在Swan外部类中构造了swim()方法,来调用匿名内部类对象的swim()方法。

但是,这种设计方式,有明显的缺陷。因为,Swan类本身只继承了FlyingAnimal类,所以它和FlyingAnimal是is - a的关系,它和SwimmingAnimal并没有继承关系,所以并不是is-a的关系,其实更像一种has - a的关系。所以,这并不符合常理。


2. 使用"接口+内部类"的方式实现闭包与回调

概念可参考:https://www.cnblogs.com/pangblog/p/3359832.html

                     https://baike.baidu.com/item/%E9%97%AD%E5%8C%85/10908873?fr=aladdin#2


实例(来源于《think in java》):

interface Incrementable {
	void increment();
}

class Callee1 implements Incrementable {
	private int i = 0;

	@Override
	public void increment() {
		// TODO Auto-generated method stub
		i++;
		System.out.println(i);
	}
}

class MyIncrement {
	public void increment() {
		System.out.println("Other operation");
	}
	static void f(MyIncrement mi) {
		mi.increment();
	}
}

class Callee2 extends MyIncrement {
	private int i = 0;
	public void increment() {
		super.increment();
		i++;
		System.out.println(i);
	}
	
	private class Closure implements Incrementable {

		@Override
		public void increment() {
			// TODO Auto-generated method stub
			Callee2.this.increment();
		}
		
	}
	
	Incrementable getCallbackReference() {
		return new Closure();
	}
}

class Caller {
	private Incrementable callbackReference;
	Caller(Incrementable cbh){
		callbackReference = cbh;
	}
	void go(){
		callbackReference.increment();
	}
}

public class Callbacks {
	public static void main(String[] args) {
		Callee1 c1 = new Callee1();
		Callee2 c2 = new Callee2();
		MyIncrement.f(c2);
		Caller caller1 = new Caller(c1);
		Caller caller2 = new Caller(c2.getCallbackReference());
		caller1.go();
		caller2.go();
	}
}

在此例中,Callee1是简单的解决方式,直接实现了Incrementable接口,并复写了increment()方法。

Callee2则继承了MyIncrement(该类并未实现Incrementable接口,但也有increment()方法,该方法与Incrementable接口中的increment()方法毫不相干),就不能为了Incrementable的用途而复写increment()方法了。于是,只能使用内部类独立地实现Incrementable接口(接口+内部类)。


猜你喜欢

转载自blog.csdn.net/tca0819/article/details/80455480