接口的由来
抽象类中可以定义抽象方法的 。
当一个抽象类中的方法全是抽象的。
这时,可以通过另一种特殊的形式来体现。
用接口来表示。
接口该如何定义呢?
interface
接口的定义
接口中的成员已经被限定为固定的几种。
【接口的定义格式先介绍两种:】
1,定义变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称之为常量。
2,定义方法,方法也有固定的修饰符,public abstract
接口中的成员都是公共的。
//定义一个名称为Demo的接口。
interface Demo
{
public static final int NUM1 = 3;
//编译器会自动加上 public static final
int NUM2 = 3;
public abstract void show1();
//编译器会自动加上 public abstract
void show3();
public abstract void show2();
}
//定义子类去覆盖接口中的方法。
//子类必须和接口产生关系,类与类的关系是继承,类与接口之间的关系是 实现。通过 关键字 implements
//子类实现Demo接口。
class DemoImpl implements Demo
{
//重写接口中的方法。
public void show1(){}
public void show3(){};
public void show2(){}
}
接口的思想
1,接口的出现对功能是实现了扩展。
2,接口的出现定义了规则。
3,接口的出现降低了耦合性(解耦)。
接口的出现,完成了解耦,说明有两方,一方在使用这个规则,另一方在实现这个规则。
比如笔记本电脑使用这个规则,而外围设备在实现这个规则。
接口的特点
1,接口不可以创建对象。
2,子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。
否则子类是一个抽象类。
【接口最重要的体现】
解决多继承的弊端。将多继承这种机制在java中通过多实现完成了。
interface A
{
void show1();
}
interface B
{
void show2();
}
// 多实现。同时实现多个接口,有利于多态。
class C implements A,B
{
public void show1(){}
public void show2(){}
}
【怎么解决多继承的弊端呢?】
弊端:多继承时,当多个父类中有相同功能时,子类调用会产生不确定性。
其实核心原因就是在于多继承父类中功能有主体,而导致调用运行时,不确定运行哪个主体内容。
为什么多实现就解决了呢?
因为接口中的功能都没有方法体,由子类来明确。
interface A
{
void show();
}
interface B
{
void show();
}
class C implements A,B// 多实现。同时实现多个接口。
{
public void show();
}
C c = new C();
c.show();
基于接口的扩展
接口的出现避免了单继承的局限性。
父类中定义的事物的基本功能。
接口中定义的事物的扩展功能。
子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。
如果子类想要继续扩展其他类中的功能呢?这时通过实现接口来完成。
class Fu
{
public void show(){}
}
//子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。
//如果子类想要继续扩展其他类中的功能呢?这时通过实现接口来完成。
interface Inter
{
pulbic void show1();
}
class Zi extends Fu implements Inter
{
public void show1()
{
}
}
接口出现后的一些小细节
类与类之间是继承(is a)关系,类与接口之间是实现(like a)关系,
接口与接口之间是继承关系,而且可以多继承。
interface InterA
{
void show1();
}
interface InterAA
{
void show11();
}
//接口的多继承。
interface InterB extends InterA,InterAA
{
void show2();
}
class Test implements InterB
{
public void show1(){}
public void show2(){}
public void show11(){}
}
class InterfaceDemo
{
public static void main(String[] args)
{
DemoImpl d = new DemoImpl();
d.show1();
d.show2();
}
}
没有抽象方法的抽象类的由来
问题:
为了使用接口中的部分方法。而覆盖了全部的方法,而且每一个子类都要这么做,复用性差。
interface Inter
{
//定义四种显示功能。
public void show1();
public void show2();
public void show3();
public void show4();
}
//定义子类,要使用第一种显示方式。
class InterImpl1 implements Inter
{
//覆盖show1方法。
public void show1()
{
System.out.println("show1 run");
}
//为了让该类实例化。还需要覆盖其他三个方法,虽然该类用不上。
public void show2(){}
public void show3(){}
public void show4(){}
}
//另一个子类需要使用显示3方法。
class InterImpl3 implements Inter
{
//覆盖show3方法。
public void show3()
{
System.out.println("show3 run");
}
//为了让该类实例化。还需要覆盖其他三个方法,虽然该类用不上。
public void show2(){}
public void show1(){}
public void show4(){}
}
class InterfaceDemo2
{
public static void main(String[] args)
{
InterImpl1 in1 = new InterImpl1();
in1.show1();
InterImpl3 in3 = new InterImpl3();
in3.show3();
}
}
解决方案
将所有的方法都单独抽取到一个独立的类中。
让这个类去实现接口,并覆盖接口中的所有方法。
这个类知道这些方法的具体实现内容吗?不知道。
所以只能为了后期子类创建对象方便,而进行空实现。
而这时,这个类创建对象有意义吗?没有意义。这个类创建对象就不需要,直接将其抽象化。
有人可能考虑构造函数private来阻止这个类创建对象,那么继承的子类都不能初始化,所以只能用将类抽象。
这就是没有抽象方法的抽象类。
abstract class InterImpl implements Inter
{
//实现Inter接口中的所有方法。
public void show1(){}
public void show2(){}
public void show3(){}
public void show4(){}
}
//如果有子类去使用显示1方法。让子类继承InterImpl实现类就可以了。
class InterImpl11 extends InterImpl
{
public void show1()
{
System.out.println("show1 run");
}
}
class InterImpl33 extends InterImpl
{
public void show3()
{
System.out.println("show3 run");
}
}
class InterfaceDemo2
{
public static void main(String[] args)
{
InterImpl1 in1 = new InterImpl1();
in1.show1();
InterImpl3 in3 = new InterImpl3();
in3.show3();
}
}
接口和抽象类的区别
抽象类是描述事物的基本功能,可以定义非抽象的方法。
接口中定义只能是抽象方法,负责功能的扩展。类与类之间是继承关系 is a关系。
类与接口之间是实现关系 like a 关系。