接口与内部类
一、接口概述
概述与特点
概述:是一个特殊的抽象类;只是接口没有继承关系
接口的主要作用是在实现多态上
接口中的方法都是抽象方法(除非有特殊设定),更形象的去使用多态
语法设计: 接口与实现类的关系
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()
} }