Java抽象类和接口

前言

各位朋友们,大家好!大家五一玩的开心吗?今天我为大家分享的是Java的抽象类和接口,大家听到抽象类和接口可能就会想它到底有多抽象呢?很多初学者在学完了抽象类和接口之后可能大脑里面还没有抽象类和接口这个概念,也就像我们在学习离散数学的时候一样,课上跟着老师的步伐走可能当时能理解,但是每当下课铃声一响,你的脑子一片空白,并且在写老师布置的作业的时候会想:这个知识老师讲过了吗?大家别急,今天这篇文章我将带大家好好领略抽象类和接口的神奇之处。

抽象类

为什么会有抽象类这个概念

前面我们的大家可能都学过了继承,如果没学也别急,大家可以看看这篇文章Java继承(不能再留遗憾了)我们可以使用继承来将类的共性给提取出来作为父类来降低代码的复用率,但是我们想一想是不是有了继承就解决了一切呢?NO NO NO当然不是,我们来看一个例子:

class Animal {
    String name;
    float weight;

    public Animal(String name, float weight) {
        this.name = name;
        this.weight = weight;
    }

    public void Eat() {
        System.out.println(name+"吃猫粮");
    }
}

class Cat extends Animal{
    public Cat(String name, float weight) {
        super(name, weight);
    }
}

class Dog extends Animal {
    public Dog(String name, float weight) {
        super(name, weight);
    }
}

public class Main {
    public static void main(String[] args) {
        Cat cat = new Cat("小花",20);
        cat.Eat();
        Dog dog = new Dog("大黄",30);
        dog.Eat();
    }
}

在这里插入图片描述

我们都知道猫和狗一般都有名字,有体重等等,都会吃东西,所以我们将这些共性提取到Animal父类中,然后猫和狗继承Animal类也就继承了父类的成员变量和成员方法,但是当我们调用子类猫和狗的Eat方法时,我们会发现狗也吃猫粮?这显然是不合理的,因为就算他们都能吃东西,但是他们吃的食物的种类是不同的,我们在父类中将Eat的方法给实现了就太局限了,所以这里我们就出现了抽象类,抽象类可以很好的解决这个问题。

什么是抽象类

抽象类是指被abstract关键字修饰的类。抽象类中可以有普通的成员变量,可以有普通的成员方法也可以有抽象方法。抽象方法是指被abstract修饰的没有方法体的方法,这也就类似于我们C语言的函数的声明,这里只是告诉你我要使用这个方法,但是具体怎样使用,我不告诉你。抽象方法的实现需要你继承了这个子类来实现,我们的抽象方法不需要考虑这个。但是我们需要知道的是:既然他是抽象方法,什么是抽象?就是我们触摸不到的东西,是我们需要脑子想出来的东西,所以抽象类不能被实例化,也就是说抽象类无法使用new这个关键字实例出对象,他只能被子类继承,并且你的子类必须重写你父类的所有抽象方法,否则,你的子类也是一个抽象类。说到重写,我们知道你要想被重写就不能使用private和final来修饰你的抽象方法。
在这里插入图片描述
在这里插入图片描述
如果用private或者final来修饰你的抽象方法,编译器将会报错,这也会使你尽早发现你的错误。

在这里插入图片描述

当你的子类没有重写父类的所有抽象方法时,编译器同样会报错,你要不就是用abstract修饰这个类,使这个类也成为抽象类,但是你欠下的早晚都要还的,既然你的这个类是抽象类,你也需要别的类来继承你的这个抽象类,你要想别的类不为抽象类,你不仅需要重写这个类的抽象方法,还需要将这个类没有重写的父类抽象类的抽象方法重写,所以我们还是将这个抽象方法重写了最好。

abstract class Animal {
    String name;
    float weight;

    public Animal(String name, float weight) {
        this.name = name;
        this.weight = weight;
    }

    abstract void Eat();
}

class Cat extends Animal {
    public Cat(String name, float weight) {
        super(name, weight);
    }
    public void Eat() {
        System.out.println(name+"吃猫粮");
    }
}

我们使用抽象类来解决开头的问题。

abstract class Animal {
    String name;
    float weight;

    public Animal(String name, float weight) {
        this.name = name;
        this.weight = weight;
    }

    abstract void Eat();
}

class Cat extends Animal {
    public Cat(String name, float weight) {
        super(name, weight);
    }
    public void Eat() {
        System.out.println(name+"吃猫粮");
    }
}

class Dog extends Animal {
    public Dog(String name, float weight) {
        super(name, weight);
    }

    public void Eat() {
        System.out.println(name+"吃狗粮");
    }
}

public class Main {
    public static void main(String[] args) {
        Cat cat = new Cat("小花",20);
        cat.Eat();
        Dog dog = new Dog("大黄",30);
        dog.Eat();
    }
}

在这里插入图片描述
见识到抽象类的功能强大了没,既然抽象类就这么强大,那么我们来看看比抽象类更加抽象的-接口。

接口

什么是接口

为什么说接口是比抽象类更加抽象呢?因为在抽象类中可以有普通成员变量和方法,但是在接口中不存在普通的成员变量和普通方法,接口中只能有被public static final修饰的成员变量和public abstract修饰的抽象方法,但是在JDK8之后接口中可以存在default修饰的普通方法。

接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。
在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。

如何定义接口以及如何实现接口

定义一个接口

在定义接口的时候,我们只需要将定义类的时候的class换成interface就可以了。

public interface 接口名称{
	public static final int a;
	int b;
// 抽象方法
	public abstract void method1(); // public abstract 是固定搭配,可以不写
	public void method2();
	abstract void method3();
	void method4();
// 注意:在接口中上述写法都是抽象方法,跟推荐方式4,代码更简洁
}

我们在定义成员变量或者方法时可以将public static final 和public abstract省略,在接口中成员方法会被默认为public static final修饰的,抽象方法也会被默认为public abstract。并且通常接口的名称是以“I”开头的。

实现接口

跟继承类似,我们用implements关键字来实现接口。

public class 类名称 implements 接口名称{
	// ...
}
public interface IRunning {
    void running();
}

public interface ISwimming {
    void swimming();
}

public interface IFlying {
    void flying();
}

class Cat implements IRunning {
    @Override
    public void running() {
        System.out.println("猫会走");
    }
}

class Fish implements ISwimming {
    @Override
    public void swimming() {
        System.out.println("鱼会游泳");
    }
}

class Bird implements IFlying {
    @Override
    public void flying() {
        System.out.println("鸟会飞");
    }
}

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.running();
        Fish fish = new Fish();
        fish.swimming();
        Bird bird = new Bird();
        bird.flying();
    }
}

在这里插入图片描述

我们定义不同的接口,那些类具有这些特性,需要使用它,就直接实现它,这极大的提高了代码的灵活性。

实现多个接口

不仅如此,我们一个类还可以实现多个接口,这也可以说是解决了Java不能多继承的问题。


class frog implements ISwimming,IRunning {
    @Override
    public void swimming() {
        System.out.println("青蛙会游泳");
    }

    @Override
    public void running() {
        System.out.println("青蛙会走");
    }
}

接口之间的继承关系

接口与接口之间可以有继承关系,并且接口与接口之间可以多继承,也可说是接口的拓展。

public interface IRunning {
    void running();
}

public interface ISwimming {
    void swimming();
}

public interface IAmphibious extends IRunning,ISwimming{

}

class frog implements IAmphibious {
    @Override
    public void swimming() {
        System.out.println("青蛙会游泳");
    }

    @Override
    public void running() {
        System.out.println("青蛙会走");
    }
}

通过接口继承创建一个新的接口 IAmphibious 表示 “两栖的”. 此时实现接口创建的 Frog 类, 就继续要实现 running 方法, 也需要实现 swimming 方法.

抽象类和接口的区别

抽象类和接口都是Java中用于实现抽象类的机制,它们都不能被实例化,但是在使用方式、语法和用途方面有所不同。

1.实现方式

抽象类用关键字abstract来定义,包含普通方法、抽象方法、成员变量、成员方法和构造函数等,并且可以包含非抽象的方法实现。而接口是一组没有实现的特定方法集合,用关键字interface来定义,它不能包含非常量的成员变量,只能包含方法签名和常量。

2.继承方式

一个类只能继承一个抽象类,因为Java不支持多重继承。而接口支持多重继承,因为一个类可以实现多个接口。

3.方法实现方式

在抽象类中,可以有非抽象的方法实现,子类可以直接继承和使用这些方法。而在接口中,所有的方法都是抽象的,必须在实现类中实现所有的方法。

4.操作能力

抽象类可以作为一个实现类,它可以有一些已经实现好的方法,而且也可以定义一些抽象的方法,由子类实现。而接口只是一个描述行为的规范,不能有方法实现。只有某个类实现了这个接口,才能使用该接口中定义的方法。

5.应用场景

抽象类通常用于为所有的子类提供公共的方法或属性,在框架和类库的设计中较为常见。而接口通常用于定义与实现类无关的、普适性的方法,更多地用于描述类之间的通信、约定和功能规范。

综上所述,虽然抽象类和接口都是Java中实现抽象类的机制,但是它们的设计目标、实现方式、继承方式、方法实现方式以及应用场景等方面存在一些明显的差别。

总结

在Java中,抽象类和接口都是用于定义抽象类、协议或规范的工具。抽象类用于为所有子类提供一个公共的接口,它通过定义抽象方法、非抽象方法、变量和常量等实现这种目的。接口则是一组没有实现的特定方法集合,通过实现接口,一个类可以定义一组行为或功能规范,而不需要对其进行具体实现。在实际编程中,应该根据具体的业务需求选择合适的方式来进行定义和实现。

  • 67
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 98
    评论
评论 98
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不能再留遗憾了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值