Thinking in Java 笔记(四)

一、接口

    C++的多继承带来了诸如虚基类、控制规则和横向指针类型转换等复杂的特性,Java 删繁就简,只支持单一继承方式,对于多继承的特性可以使用接口Interface 来实现。接口统一定义了一组需求描述,实现这个接口的类都遵守这些接口描述,必须覆盖接口定义的方法(即规则),这就解决了很多没有 "is-a" 关系的类硬生生地继承自某个类的问题,在逻辑上用interface 实现的是 “like -a ”的关系。
	接口——全是抽象方法的集合,只有方法的声明,成员变量默认都是static final 类型,成员方法必须是public访问域。使用interface 取代关键字 class,接口之间可以多重继承。使用接口的原因:为了能向上转型为多个类型,这是多继承的变种,也防止此类被创建。接口弥补了类的不能多继承缺点,继承和接口的双重设计既保持了类的数据安全也变相实现了多继承。

public class InterfaceTest implements Test{
	//void play(){}//attempting to assign weaker access privileges; 这么写编译不通过,需要声明为public
	public void play(){System.out.println("playing ....");}
	public static void main(String[] args){
		new InterfaceTest().play();
	}
}
//默认是同包访问,不能在一个文件中声明两个public的类,接口的方法自动属于public的. 接口间可以多重继承
<strong>interface</strong> Test <span style="color:#ff6600;">extends a,b</span>{//error: class Test is public, should be declared in a file named Test.java
	void play();//access: public
}
interface a{}
interface b{}

接口与抽象类的区别:

1)接口中全部是抽象方法,实体域自动属于public static final,必须赋初值;抽象类可以有0-n个抽象方法,实体域可被子类更改

2)接口的方法自动属于public abstract,实现类必须全部重写方法;抽象类的方法可以是任意的访问权限,可以包含非abstract方法

3)接口可以多重继承接口,一个类可以implements多个接口;抽象类是属于一个类,单一继承extends

4)接口用interface 修饰; 抽象类是 abstract class 修饰

二、内部类

接口与内部类为我们提供了一种将接口定义与实现分离的更加结构化的方法

    内部类:定义在类或方法内部的类。

    普通的内部类对象隐式地保存了一个指向创建它的外围类对象的引用,可以访问外围类的所有属性和方法。static修饰的内部类除外,因为它是属于类共有而不是某个对象。

创建内部类之前要先创建外部类,因为内部类很有可能访问外部类的成员(内部类有访问所有外部类成员的权利),如果不先构造外部类就会出现错误,这就像是子类如果不先构造父类就会出现错误一样。

public class OuterClass{
	private int id;
	public OuterClass(int i){
		this.id=i;
		System.out.println("build outer class "+i);
	}
	public class InnerClass{
		public OuterClass getOuter(){
			return OuterClass.this; <strong>//只能通过类名.this 得到包含当前内部类的外部类对象实例</strong>
		}
		public InnerClass(){//内部类可以直接访问外部类的成员变量
			System.out.println("create "+getClass().getSimpleName()+" "+id+" of "+getOuter().getClass());
		}
	}	
	public static void main(String []args){
		OuterClass outer=new OuterClass(10);
		<strong>OuterClass.InnerClass</strong> inner=outer.new InnerClass();<strong>//创建内部类的方法,外部类实例.new 内部类名()</strong>		<span style="white-space:pre">	</span>//内部类必须在外部类的命名空间下才能创建,外部类名.内部类名才代表这个内部类
	}
}
/** Results:
*build outer class 10
*create InnerClass 10 of class OuterClass
*/

有一个类Child,它既想继承Parent的count()方法,又想实现ICount接口中的count方法,这个时候怎么办呢?内部类就可以大显身手了: 

interface ICount { 
int count(); 
} 
class Parent { 
int i = 0; 
int count() { 
return i++; 
} 
} 
class Child extends Parent { 
ICount getCount() { 
 return new ICount { 
  int i = 0; 
  int count() { 
  return (i *= 2); 
  } 
 } 
 } 
} //这样的话就可以调用getCount().count() 方法和直接调用count方法了




嵌套类:静态的内部类。可以用来包含测试代码,在发布的时候删掉它即可。内部类经过编译后是以Outer$Inner的名字 出现的类文件,如果用它包含测试代码,发布工程的时候将这些删掉即可,而不必在每个类中都加一个main方法,造成类的冗余。



局部内部类:在方法内部定义的类,对外界完全地隐藏起来。它可以访问局部变量,这些变量必须声明为final型的。如果要改变这个final类型的数据,可以利用长度为1的数组来实现,把final 修饰的(引用)变量指向这个数组,数组的地址虽然不会变,但是数组的值可以变。

匿名内部类:没有名字的类,是直接以父类来创建的类,一般要覆盖某些方法。这在编写事件监听器相关的程序时会经常用到,很方便。

      内部类的好处是让外部类不必实现或者继承一些只会用到部分功能的类或接口,代码更加简洁高效,减少了类的数量。它使得多重继承解决方案变得完整。

Frankly speaking,接口虽很好,但是设计时优先使用类而不是接口。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值