接口与内部类

一、接口概述

概述与特点

概述:是一个特殊的抽象类;只是接口没有继承关系

接口的主要作用是在实现多态上

接口中的方法都是抽象方法(除非有特殊设定),更形象的去使用多态

语法设计: 接口与实现类的关系

interface 接口名{

​ 抽象方法;

}

class 实现类 implements 接口{

​ 重写抽象方法;

}

与抽象类的异同

相同点:

都可以生成class文件

都不能具体化(不能实例化对象)

都可以调用Object的所有方法(继承性-Object是老祖宗)

都可以作为引用类型(多态应用)

不同点:

接口中定义的属性是公开的静态常量 默认加:public static final

接口中定义的方法为公开的抽象方法 默认加:public abstract

接口中不能有构造方法,没有静态代码块和动态代码块二

二、应用场景

接口与抽象类类似,就是为多态而生;在应用场景上也是一样的

直接多态

当我们的案例中,表示一种特殊的能力或功能时,则可使用直接引用多态

案例:喷火哇具有喷火的能力

分析:类-娃娃类 接口-可喷火接口 方法-喷火

//案例:喷火娃具有喷火的能力
interface Fireable{ //喷火能力-接口
	int age=20;       //默认+public static final  使用反编译工具查看
	
	//能力的具体体现
	void fire();   //默认+public abstract
    
    default void test() { //不能有成员方法 --可以加default
	}
}
//处理异常:1.把自身变抽象  2.重写抽象方法
/*abstract*/ class WaWa implements Fireable{  //实现类

	@Override
	public void fire() {
		System.out.println("喷火娃正在喷火");
	} 
	public void print() { //实现类的独有方法
		System.out.println("普通打印");
	}
}
public class Test1 {
	public static void main(String[] args) {
		//Fireable able = new Fireable();   //不能具体化
		Fireable able = new WaWa();  //直接引用多态
		able.fire();  //多态调用实现类重写方法
		//able.print();  //不能调用实现类独有方法; 除非强转
		if (able instanceof WaWa) { //强转有隐患,可以使用instanceof匹配
			WaWa wa = (WaWa) able; 
			wa.print();
		}
	}
}

综合引用案例

在案例中,即可实现接口直接引用多态,也可以实现抽象类直接引用多态

//综合案例:把狗当成动物看待,可调用吃的方法;把狗当成可跑的东西,调用跑的方法
//分析:类-狗(子),动物(抽象父) 接口-可跑的   方法:吃、跑
/*
 * 整理类与类的关系:
 * 类与类-------单继承
 * 类与接口-----多实现
 * 接口与接口---多继承
 * 
 * 接口的特点:实现类可继承另一个类,并实现多个接口
 * */
abstract class Animal{
	public abstract void eat();
}
interface Runable{ //跑的接口
	void run();    //能力的体现
}
interface ITest{}
interface ITest2{	
}
interface ITest3 extends ITest,ITest2{
	
}
class Dog extends Animal implements Runable,ITest{
	@Override
	public void eat() {
		System.out.println("旺财正在吃...");
	}
	@Override
	public void run() {
		System.out.println("旺财正在跑...");
	}
	public void print() {
		System.out.println("旺财独有方法..");
	}
}
public class Test2 {
	public static void main(String[] args) {
		//1.面向对象应用:
		Dog dog = new Dog(); //把狗当都看到,可调所有方法
		//dog.eat();dog.run();dog.print();
		
		//2.面向抽象:  抽象类实现多态
		Animal animal = new Dog(); //把狗当动物看待,可调父类方法或子类重写方法
		animal.eat();  //父类提供的模板;子类重写了
		
		//3.面向接口: 接口实现多态
		Runable run = new Dog();  //把狗当能跑的东西看待,可调跑的方法
		run.run();    //调用实现类重写方法
	}
}

传参多态

接口使用传参多态的场景:将接口当成标准或规范或约定

接口实现多态的好处:可扩展性,维护性更强;解耦合(只需一个接口引用);更容易更换具体实现;容易模块分离

//案例:电脑连接usb标准的鼠标,硬盘...
//分析:类-电脑(第三分类),鼠标,硬盘  接口-usb标准  方法:连接,运转
interface USB{ //usb标准
	void run();  //标准的体现
}
class Mouse implements USB{
	@Override
	public void run() {
		System.out.println("鼠标正在运转");
	}
}
class Disk implements USB{
	@Override
	public void run() {
		System.out.println("硬盘正在运转");
	}
}
class Computer{
	//接口传参实现多态:接口引用指向实现类对象,可调用实现类重写方法
	public void connect(USB u) { //USB u = new Mouse();
		u.run();   //接口回调
	}
}
public class Test1 {
	public static void main(String[] args) {
		Computer com = new Computer();
		com.connect(new Mouse()); //电脑连接鼠标
		com.connect(new Disk());  //电脑连接硬盘
	}
}

综合传参案例

抽象类与接口以传参形式实现多态的案例

//案例:人开门;门有安全门,超级门;具有人脸识别及指纹识别标准
//分析:类-人,门(抽象类)安全门,超级门     接口-人脸识别,指纹识别
  //方法: 开     开的状态      人脸检测    指纹检测

//问题:能否将人脸与指纹的接口统一到一起?
//不可以,因为安全门强行加了一个具体实现,这个是安全门不具备的实现
//面向对象设计原则:ISP-接口隔离原则
//接口与接口之间尽可能独立,只完成一个功能
abstract class Door{
	public abstract void info();  //开的状态
}
class SafeDoor extends Door implements IZhiWen{
	@Override
	public void info() {
		System.out.println("安全门打开了~~!");
	}

	@Override
	public void jiance() {
		System.out.println("指纹检索安全门成功~~!");
	}
}
class SuperDoor extends Door implements IZhiWen,IFace{
	@Override
	public void info() {
		System.out.println("超级防盗门打开了~~");
	}

	@Override
	public void jiance() {
		System.out.println("指纹检索超级门成功~!");
	}

	@Override
	public void jiance2() {
		System.out.println("人脸检测超级门成功~");
	}
}
interface IZhiWen{  //指纹检测的接口
	void jiance();
}
interface IFace{    //人脸检测的接口
	void jiance2();
}
class Person{
	public void open(Door d) {
		d.info();  //传参多态
	}
	
	public void zhiWenCheck(IZhiWen zw) { //传参多态
		zw.jiance(); //谁传给我,就检测谁
	}
	
	public void faceCheck(IFace face) { //接口传参多态
		face.jiance2();
	}
}
public class Test2 {
	public static void main(String[] args) {
		//1.抽象类传参多态
		Person p = new Person();
		p.open(new SafeDoor());  //人开安全门
		p.open(new SuperDoor()); //人开超级门
		
		//2.接口传参多态
		p.zhiWenCheck(new SafeDoor()); //人检测安全门
		p.zhiWenCheck(new SuperDoor()); //人检测超级门
		
		p.faceCheck(new SuperDoor());  //人检测超级门
	}
}

三、常量接口

概述:就是将静态常量放入了接口中,来充当状态值的使用

返回值多态案例

//返回值多态案例:
//我要购买usb标准的设备: 1.鼠标   2.硬盘
//分析:类-Person  Mouse,硬盘   接口:usb标准   方法:购买,使用
interface USB{
	int MOUSE = 1;  //状态值--接口常量
	int DISK = 2;  
	void use();  //usb设备使用的方法
}
class Mouse implements USB{

	@Override
	public void use() {
		System.out.println("usb标准的鼠标正在使用...");
	}
}
class Disk implements USB{

	@Override
	public void use() {
		System.out.println("usb标准的硬盘正在使用");
	}
}
class Person{
	public USB bug(int flag) {
		if(flag==USB.MOUSE) {
			return new Mouse();
		}else if(flag==USB.DISK) {
			return new Disk();
		}else {
			return null;
		}
	}
}
public class Test1 {
	public static void main(String[] args) {
		Person p = new Person();
		USB usb = p.bug(USB.MOUSE);
		if(usb!=null) {
			usb.use();
		}
	}
}

四、内部类

概述:在一个类的内部又创建了类,创建的类就叫做内部类

特点:

内部类会产生独立的class文件

外部内的资源可以直接在内部类中使用,而不破坏封装性

外部类的一些组件功能,可以交给内部类来完成

分类:成员内部类,静态内部类,局部内部类(了解),匿名内部类(重点)

成员内部类

在一个类中创建的普通的类

class Outter{
	private String name="凤姐";
	
	public void print() {
		new Inner().test();  //外部类的一些功能,可以交给内部类来完成
	}
	class Inner{  //成员内部类
		String name = "芙蓉";
		//static int age = 30; //在成员内部类中,不能使用静态变量--加载时机有关
		public void test() {
			System.out.println(name);  //可以调用外部类的属性
			System.out.println(Outter.this.name); //调用外部类的属性
		}
	}
}
public class Test1 {
	public static void main(String[] args) {
		Outter out = new Outter();  //1.使用外部类来调用内部类方法
		out.print();
		
		//2.直接调用内部类方法: 通过外部类对象,产生内部类对象
		Outter.Inner inner = new Outter().new Inner();
		inner.test();
	}
}

静态内部类

在一个类的内部创建一个static修饰的内部类

class Outter2{
	private String name="凤姐";
	private static int    age = 30;
	static class Inner2{ //静态内部类
		public void print() {
			//System.out.println(name); //在静态内部类中不能使用成员变量
			System.out.println(age);    //可以使用外部类的静态成员变量
			System.out.println("内部类方法的调用");
		}
	}
}
public class Test2 {
	public static void main(String[] args) {
		//调用静态内部类1:通过类名来调资源
		Outter2.Inner2 inner2 = new Outter2.Inner2();
		inner2.print();
		
		//简化版:直接导包 ...Outter2.Inner2
		Inner2 in = new Inner2();
		in.print();
	}
}

局部内部类

//局部内部类:在外部类的方法中定义的类
//应用:在外部类的方法中,才能使用局部内部类(很少用);不能使用public修饰
class Outter3{
	String name = "张三";
	public void show() {
		 int age = 30;
		class Inner3{ //局部内部类
			public void test() {
				System.out.println("调用局部内部类--"+name);
				//age = 40; //外部类方法中定义的变量,会自动变为常量  +final
				//原因是age的作用域要与局部内部类保持一致
				System.out.println(age);
			}
		}
		
		new Inner3().test();  //在当前方法中,才能调用局部内部类
	}
}
public class Test3 {
	public static void main(String[] args) {
		new Outter3().show();;
	}
}

五、总结与作业

总结

作业

1、自定义接口Play,及实现类Dog 实现接口方法play,狗类重写play进行抓飞碟方法,进行测试
2、实现防盗门:创建抽象类Door、接口Lock 定义上锁方法、接口Bell定义门铃方法,创建类AntiThiefDoor,继承及实现接口
3、创建打印机类Printer,打印机使用墨盒打印
接口InkBox墨盒方法为获取颜色,
Colorink和Blackink两个实现类实现彩色和黑白墨盒,
创建测试类测试接口回调
4、内部类的特点;以及有哪些内部类?
5、请在以下代码的基础上完成下面几个小题 
(1)在①和②的位置标注出内部类和外部类 
(2)在③的位置定义一个count变量用来存放Circle实例的个数,并在④的位置编写语句用来统计Circle实例的个数。 
(3)在⑤和⑥处根据注释语句填写代码  
(4)在main()⑦的位置上编写语句调用Draw类中的drawSahpe()。 :
 class Circle {  //①   _________________
	private double radius = 0; 
	③  _________________
	 public Circle(double radius) {        
		 this.radius = radius;       
		  ④  _________________                         
	  }      
    	class Draw {   //②  _________________                              
		  public void drawSahpe() { 
           		 ⑤ _________________  //输出radius变量的值 
	                 ⑥ _________________ //输出count变量的值        
	 }     } } 
public class OuterInnerClass {  
	public static void main(String[] args) {          
		⑦ _________________ //编写语句调用Draw类中的drawSahpe() 
		
} }