抽象类和接口
抽象类
抽象类:如果一个类中没有足够的信息来描绘一个对象,那么这个类就是抽象类
抽象类入门
- 矩形、三角形、圆形类都是图形类,因此和Shape的关系应该是extends
- 虽然Shape类中也有draw方法,但是Shape并不是具体的图形,因此内部的画图的方法是没有方法具体实现的
- Shape类没有办法描述一个具体的图形,那么里面的draw方法也就没有办法来实现,因此就可以将Shape设置为abstract修饰的抽象类,将draw设置为abstract修饰的抽象方法。
注意:
抽象类也是类,内部可以包含普通方法和属性,甚至构造方法
当抽象类里面有抽象方法后,这个抽象方法必须要在子类中重写该抽象方法。
代码实现
解读:
- Animal是一个动物类,每个Animal都有叫的方法,但是Animal不是一个具体的动物,所以Animal这个类里面的bark()方法就无法具体的实现。
- Dog是狗类,首先狗是一个动物,与Animal是继承的关系,狗是一个具体的动物,然后狗这个类就可以实现bark方法具体是怎么叫的
- Cat是猫类,首先猫是一个动物,与Animal是继承的关系,猫是一个具体的动物,然后猫这个类就也可以实现bark方法具体是怎么叫的
抽象类得语法:
一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用 给出具体的实现体。
package ClassANDObject.Abstract.Abstract01;
abstract class Animal {
//注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract void bark();//抽象类可以不写方法的实现
}
class Dog extends Animal{
public Dog(String name) {
super(name);
}
@Override
public void bark() {//重写了抽象类
System.out.println("小狗 "+getName()+" 正在汪汪叫");
}
}
class Cat extends Animal{
public Cat(String name) {
super(name);
}
@Override
public void bark() {//重写了抽象类
System.out.println("小猫 "+getName()+" 正在咪咪叫");
}
}
public class test{
public static void show(Animal animal){//用多态思想去调用
animal.bark();
}
public static void main(String[] args) {
// Animal animal = new Animal(); 抽象类不能直接实例化对象 因为类是一个抽象的类。
Dog dog = new Dog("大黄");
Cat cat = new Cat("小花");
//直接调用
/*dog.bark();
cat.bark();*/
Animal[] animal = {dog,cat};//用多态思想去调用
for (Animal a:animal) {
a.bark();
}
show(dog);
show(cat);
}
}
抽象类的使用细节
-
抽象类可以不写具体的实现,但是方法要用abstract修饰 —>抽象方法
-
抽象类不能直接实例化对象 因为类是一个抽象的类。
-
Animal animal = new Animal(); //报错 java: ClassANDObject.Abstract.Abstract01.Animal是抽象的; 无法实例化
-
抽象方法不能private的 抽象方法必须要用abstract修饰,private不能同时修饰一个方法。
-
当一个普通类继承了抽象类,必须重写抽象类当中的抽象方法
-
抽象方法不能被final static修饰,因为子类最终要重写抽象方法来实现具体的事物。
-
抽象类存在最大的意义就是为了被继承
-
抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修饰。
-
抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类。
-
只要包含抽象方法,这个类必须是抽象类
-
抽象方法是一定要重写的,所以一定要满足方法重的规则
-
抽象类中不一定包含抽象方法
-
抽象类中可以有构造方法,用于子类初始化父类的成员变量
-
抽象类的价值在与设计,是设计者在设计好之后,让子类继承并实现抽像类
抽象类和普通类的区别
抽象类不能被实例化 普通类可以
抽象类当中可以包含非抽象方法和抽象方法,但是普通类只能包含非抽象方法
抽象类总结
抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类. 然后让子类重写抽象类中的抽象方法
接口
接口的概念
接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。 在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
接口:制定一个标准,是一个行为的规范
接口快速入门
interface IShape{
void draw();//接口里面指定一个标准 行为的一种规范
public static void func(){
System.out.println("这是一个接口里面静态的方法");
}
}
class Rect implements IShape{ //这个类和接口的关系是要执行接口的标准 使用关键字 implements
@Override
public void draw() {//实现了接口里面的方法,执行接口里面的标准
System.out.println("画矩形");
}
public void info(){
System.out.println("这是Rect里面的特有的方法");
}
}
class Flower implements IShape{
@Override
public void draw() {
System.out.println("❀!");
}
public void info(){
System.out.println("这是Flower里面的特有的方法");
}
}
public class test1 {
public static void show(IShape iShape){ //向上转型 可以把接口看做一个父类
iShape.draw();
}
public static void show1(IShape iShape){ //向下转型,调用特有的方法
if(iShape instanceof Rect){
Rect rect = (Rect) iShape;
rect.info();
}else if(iShape instanceof Flower){
((Flower) iShape).info();
}
}
public static void main(String[] args) {
/* Rect rect = new Rect();
Flower flower = new Flower();*/
IShape iShape = new Rect();//向上转型
IShape iShape1 = new Flower();//向上转型
show(iShape);
show(iShape1);
//如果要调用Flower里面特有的方法,需要进行向下转型
show1(iShape);
show1(iShape1);
//如果要调用接口里面静态的方法,那么直接通过接口名来调用
IShape.func();
}
}
- 接口的定义 使用关键字interface
- 接口不能实例化
- 接口当中的成员默认是public static final 静态常量
- 接口里面的方法不能有具体的实现,只能有抽象方法 但是从jdk8开始,可以写一个default修饰的方法,就可以有具体的实现
- 接口的抽象方法默认就是public abstract 修饰的
- 接口中不存在构造方法
- 接口需要被类实现,使用关键字implements 接口里面的方法默认是抽象方法,所有要在实现接口的类中重写接口的抽象方法
- 接口当中可以有static修饰的方法
接口本质是对行为的规范和抽象
接口的使用
接口不能直接使用,必须要有一个实现类来实现接口中定义的所有抽象方法
类与类之间的关系是extends,那么类与接口之间的关系是implements
public interface USB {
//定义了两个规范
void open();
void stop();
}
public class Monse implements USB{ //实现了接口的规范
@Override
public void open() {
System.out.println("打开鼠标");
}
@Override
public void stop() {
System.out.println("关闭鼠标");
}
public void click(){
System.out.println("点击鼠标");
}
}
public class KeyBoard implements USB{ //实现了接口的规范
@Override
public void open() {
System.out.println("打开键盘");
}
@Override
public void stop() {
System.out.println("关闭键盘");
}
public void click(){
System.out.println("使用键盘");
}
}
public class Computer {
//站在我们这个方法的角度,我们不关心usb到底引用那个对象,只要实现了接口里面的规范就可以了
//发生了多态
public void usbdiv(USB usb){ //发生了向上转型
usb.open();
if(usb instanceof Monse){ //向下转型 调用特有的方法,即接口没有定义的规范
Monse monse = (Monse)usb;
monse.click();
}else if(usb instanceof KeyBoard){//向下转型
((KeyBoard) usb).click();
}
usb.stop();
}
}
public class test {
public static void main(String[] args) {
Monse monse = new Monse();
Computer computer = new Computer();
KeyBoard keyBoard = new KeyBoard();
computer.usbdiv(monse);
computer.usbdiv(keyBoard);
}
}
抽象类是对一个事物在抽象,接口是对一个行为在抽象,在设定标准
接口的特性
1:接口是一种引用类型,但是不能直接new一个接口的对象
interface USB{
}
public class A{
public static void main(String[] args){
USB usb = new USB(); //直接报错
}
}
2:接口中的每一个方法都是public 修饰的抽象方法,即接口中的方法会被隐士的写为public abstract ,如果写其他的组合会报错
3:接口中的方法不能被接口实现,只能由实现接口的类来实现 要想实现必须写default
4:重写接口的方法时,不能写默认的访问修饰权限
5:接口含有变量,但接口中的变量会被隐士的写为public static final 变量
6:接口中不能有静态代码块和构造方法
7:接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
8:如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
实现多个接口
在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接 口。下面通过类来表示一组动物.
public class Animal { //父类
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public interface Flying { //飞的接口
void fly();
}
public interface RUNing {//跑的接口
void run();
}
public interface Swim { //游泳的接口
void swimming();
}
public class Dog extends Animal implements RUNing { //子类,并实现了RUNing这个接口的规范
public Dog(String name) {
super(name);
}
@Override
public void run() {
System.out.println(getName()+"正在用狗腿跑");
}
}
public class Duck extends Animal implements RUNing,Swim, Flying {
//鸭子这个动物具备多种行为 实现了多个接口的规范
//既要实现多个接口
//这个类继承了一个父类,同时实现了多个接口
//鸭子也是一种动物, 既能跑, 也能游, 还能飞
public Duck(String name) {
super(name);
}
@Override
public void fly() {
System.out.println("鸭子"+getName()+"正在飞");
}
@Override
public void run() {
System.out.println("鸭子"+getName()+"正在跑");
}
@Override
public void swimming() {
System.out.println("鸭子"+getName()+"正在游泳");
}
}
public class Fish extends Animal implements Swim{ //子类,并实现了Swim这个接口的规范
public Fish(String name) {
super(name);
}
@Override
public void swimming() {
System.out.println(getName()+"正在游泳");
}
}
public class Frog extends Animal implements Swim, RUNing { //同时实现多个接口的规范
//青蛙这个动物具备多种行为
//既要实现多个接口
//这个类继承了一个父类,同时实现了多个接口
//青蛙是一个动物,能游泳还能跑
public Frog(String name) {
super(name);
}
@Override
public void run() {
System.out.println("青蛙"+getName()+"正在跑");
}
@Override
public void swimming() {
System.out.println("青蛙"+getName()+"正在游泳");
}
}
public class MAIN {
//在我们这个角度,我们不关心他到底是那种动物,只能是实现了相应的接口,就行
//可以不关心具体的类型,只需要关心具体的能力、行为
public static void run(RUNing runing) {
runing.run();
}
public static void Flying(Flying flying) {
flying.fly();
}
public static void swim(Swim swim) {
swim.swimming();
}
public static void main(String[] args) {
Dog dog = new Dog("旺财");
run(dog);
Duck duck = new Duck("唐老鸭");
Flying(duck);
run(duck);
swim(duck);
Fish fish = new Fish("7秒");
swim(fish);
Frog frog = new Frog("呱呱");
run(frog);
swim(frog);
}
}
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。
接口之间的继承
在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到 多继承的目的。 接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字.
interface a{
void funa();
}
interface b{
void funb();
}
interface c extends a,b{ //可以看做接口的扩展
void func();
}
class test implements c{ //这个类必须要实现继承来的所有标准,即方法。
@Override
public void funa() {
}
@Override
public void funb() {
}
@Override
public void func() {
}
}
注意:
接口间的继承相当于把多个接口合并在一起.