一转眼五一小长假就过去了,大家和自己的小伙伴们玩的开心吗?玩归玩,学习还是不能落下的,希望各位伙计们能安下心来,都有一个好的未来!
一、抽象类是什么
一听名字想必大家心中就会有些概念,类我们在前面就已经讲过了,那么抽象类又是什么呢,那就不是具体的呗,说得好有道理我竟无法反驳,感觉说了又感觉没说。
概念:在类中没有包含足够的信息来描绘一个具体的对象,这样的类称为抽象类。
抽象类的例子:
这种类的信息是不完整的,无法完整的描绘一个对象,因此也无法实例化对象,当你想要用抽象类创建对象的时候,你会发现编译器报错:
那么就会有人说了,这个抽象类看着一点都不好用,感觉很乐色,别急有反转😎。
抽象类存在的最大意义就是被继承,可以利用抽象类实现多态
这里只是定义了Cycle类,我们当然可以定义一个长方形,或是一个正方形等以此来实现多态。
看到这个还是感觉还是不如普通类来的实在,那就往下看
//抽象类和抽象方法需要被 abstract 关键字修饰
abstract class Shape{
// 抽象类中的方法一般要求都是抽象方法,抽象方法没有方法体
abstract void draw();
}
// 当一个普通类继承一个抽象类后,这个普通类必须重写抽象类中的方法
class Cycle extends Shape {
@Override
void draw() { // 重写抽象类中的draw方法
System.out.println("画一个圆圈");
}
}
class Flower extends Shape { // 不同的子类对父类的draw方法进行了不同的重写
@Override
public void draw() {
System.out.println("画一朵花");
}
}
class Square extends Shape {
@Override
public void draw() {
System.out.println("画一个正方形");
}
}
public class Main {
public static void main(String[] args) {
Cycle cycle=new Cycle();
Flower flower=new Flower();
Square square=new Square();
Shape[] shapes={flower,cycle,square};
for (int i = 0; i < shapes.length; i++) {
Shape shape =shapes[i];//向上转型,我之前的文章有介绍
shape.draw();
}
}
}
对于多态来说,他有这三个要素:
- 继承(我们刚才的Cycle类继承Shape抽象类)
- 重写(我们子类对draw方法的重写)
- 父类指向子类对象(就是shape1[0] = cycle -->也可以称作向上转型
抽象类的好处就体现出来了,抽象类不能创建实例化对象,那么我们就只能通过继承使用而抽象类中的抽像方法在被继承的子类中必须要重写,那么这样多态的条件就都满足了,是不是感觉抽象类就是为了多态而生,事实也确实如此。
那么有人就该问了,普通类不一样可以承担起继承和实现多态的任务吗?是!但是他没有抽象类安全
能看的出来,若是普通类在子类中可以不用完成父类方法的重写,编译器同时也不会报错,但要是抽象类,编译器就会报错,让你重写抽象方法。
那么说了这么多,也对抽象类做一下总结吧:
- 使用abstract修饰的类或方法,就抽象类或者抽象方法
- 抽象类是不能具体的描述一个对象,不能用抽象类直接实例化对象
- 抽象类里面的成员变量和成员方法,都是和普通类一样的,只不过就是不能进行实例化了
- 当一个普通类继承这个抽象类后,那么这个普通类必须重写抽象类当中的所有的抽象方法🤔(我们之前说过抽象类是不具体的,没有包含足够的信息来描述一个对象,所以我们需要把他补充完整)
- 但当一个抽象类A继承了抽象类B,这是抽象类A就可以不重写抽象类B当中的抽象方法
- final不能修饰抽象类和抽象方法(因为抽象类存在的最大意义就是被继承,而被final修饰的不能被继承,final和抽象,他们两个是天敌)
- 抽象方法不能被private修饰(抽象方法一般都是要被重写的,你被private修饰了,还怎么重写)
- 抽象类当中不一定有抽象方法,但如果一个类中有抽象方法,那么这个类一定是抽象类。
唱跳rap🏀
二,接口是啥
准确的说:就是更加抽象且特殊的“抽象类”,代码表示是interface。
java中接口是特殊一点的类,亦或者它不是类,但又很像,即在接口中成员变量被全局称量代替,方法也都默认是抽象方法。
那么怎样定义一个接口呢?看这个荔枝:
我们这里是定义了一个Animal的接口,既然是特殊的“抽象类”,那么有些性质还是相似的,就比如不能直接实例化对象,但是要是想要实例化对象使用,就可以通过继承,不一样的点就出现了,类与类之间是通过extends来实现的,而接口与类之间是通过implements来实现的。就像酱紫!
我们大家都知道,普通的类中只存在单继承,也就是说只能继承一个类,但是接口就可以很好地解决这个问题,接口的出现可以让我们“多继承”。就相当于生父(父类)只有一个,但是我们可以认多个干爹(通过接口)。具体是酱紫的:
//接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口
interface Eat {
// 定义变量
int a = 10; // 接口当中的成员变量默认都是public static final
// 抽象方法
void method1(); // 接口当中的成员方法默认都是public abstract, 更推荐用第二种来定义方法
}
interface color{
void method2();
}
class Dog implements Eat,color{
@Override
public void method1() {
System.out.println("沛瑜在吃翔!!!");
}
@Override
public void method2() {
System.out.println("沛瑜是黄色的!!!");
}
}
当然有颜色的,能吃东西的有很多,我们就可以将接口用到其他子类上,就比如这个荔枝:
//接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口
interface Eat {
// 定义变量
int a = 10; // 接口当中的成员变量默认都是public static final
// 抽象方法
void method1(); // 接口当中的成员方法默认都是public abstract, 更推荐用第二种来定义方法
}
interface color{
void method2();
}
class Case implements color{
@Override
public void method2() {
System.out.println("这个盒子是黄色的!");
}
}
class Dog implements Eat,color{
@Override
public void method1() {
System.out.println("沛瑜在吃翔!!!");
}
@Override
public void method2() {
System.out.println("沛瑜是黄色的!!!");
}
}
public class Main {
public static void main(String[] args) {
Dog d=new Dog();
d.method2();
d.method1();
Case c=new Case();
c.method2();
}
}
可以看到Case盒子一样可以使用color这个接口,是不是觉得接口也很方便,有了接口之后根本就不需要关注类的使用者的具体类型,只要有这个特性就可以直接使用。
抽象类和接口的区别
1.相同点:很简单就是都不能直接进行实例化。
2.不同点:
- 接口成员变量默认为public static final,必须赋初值,不能被修改。抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;
- 实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。
OK啦,今天的分享就到这里啦!大家在过了一个五一之后也不要懈怠呀!还需继续加油呀!!🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀🏀