JAVA学习日记(6)——抽象类和接口

1.抽象类

1.1 语法规则

在上一篇文章 (参考学习日记5中打印多种形状代码) 的打印图形例子中,我们发现,父类 Shape 中的 draw 方法好像并没有什么实际工作,主要的绘制图形都是由Shape 的各种子类的 draw 方法来完成的,像这种没有实际工作的方法,我们可以把它设计成一个 抽象方法(abstractmethod)

什么是抽象方法呢?

一般来说,被abstrac修饰并且没有方法体的方法我们称之为抽象方法

例如一道简单的面试题:

所有没有方法体的方法都是抽象方法吗?

错!Object类中就有很多没有方法体的方法,但是这些方法并不是抽象方法,我们是可要记住,抽象方法不仅没有方法体,还要有修饰符abstract进行修饰,这样我们才能称一个方法为抽象方法

代码示例

class Shape {
    
 	abstract public void draw(); 
}

我们在敲以上代码的时候,如果我们是在IDEA中写代码,此时会看到编译器直接给我们红线警告,说明这里存在语法错误,这里就引出我们一个点,抽象方法不能出现在普通的类中,那么我们抽象方法应该在哪里呢?很简单,我们只需要将类变成抽象的,此时就可以将我们的抽象方法放进去了,我们把包含抽象方法的类叫作抽象类

代码示例

abstract class Shape {
    
 	abstract public void draw(); 
}
  1. 在 draw 方法前加上 abstract 关键字,表示这是一个抽象方法,同时抽象方法没有方法体(没有 { },不能执行具体代码)
  2. 对于包含抽象方法的类,必须加上 abstract 关键字表示这是一个抽象类

注意事项

  1. 抽象类不能直接实例化
Shape shape = new Shape(); 
// 编译出错
Error:(30, 23) java: Shape是抽象的; 无法实例化
  1. 抽象方法不能是private的
abstract class Shape {
    
 	abstract private void draw(); 
} 
// 编译出错
Error:(4, 27) java: 非法的修饰符组合: abstractprivate
  1. 抽象类中可以包含其他的非抽象方法, 也可以包含字段. 这个非抽象方法和普通方法的规则都是一样的, 可以被重写,也可以被子类直接调用
abstract class Shape {
    
 	abstract public void draw(); 
 	void func() {
    
 		System.out.println("func"); 
 	} 
} 
class Rect extends Shape {
    
 ... 
} 
public class Test {
    
 	public static void main(String[] args) {
    
 	Shape shape = new Rect(); 
 	shape.func(); 
 	} 
} 
// 执行结果
func

1.2 抽象类的作用

抽象类存在的最大意义就是为了被继承!(生来就是当爹的~)

抽象类本身不能被实例化,要想使用,只能创建该抽象类的子类,然后让子类重写抽象类中的抽象方法

那么有的小伙伴可能就会有疑问了,为什么要用抽象类和抽象方法呢?难道它们的作用和不同方法不是一样的吗?都是可以被继承和重写的鸭

答案确实,但是!如果我们使用不同的类,这也就意味着里面的方法都要有方法体,然后再被子类重写,可以脑补一下,这个过程是不是存在了大量重复的代码,因此通过抽象类让我们可以只定义一个抽象方法,然后让子类去重写,这样就能大大的减少我们代码的工作量以及代码的重复度!那么我们可以再进一步想一想,抽象类里面出了可以出现抽象方法之外,还能出现普通方法,这样是不是也有点不太方便,那么有没有一个什么东西,能让里面只能写抽象方法呢?到这里,我们就可以引出我们的一个东西,叫作接口

2.接口

接口是抽象类的更进一步,抽象类中还可以包含非抽象方法,和字段,而接口中包含的方法都是抽象方法,字段只能包含静态常量

2.1 语法规则

在刚才的打印图形的示例中,我们的父类Shape并没有包含别的抽象方法,也可以设计成一个接口

interface IShape {
    
 	void draw(); 
} 
class Cycle implements IShape {
    
 	@Override 
 	public void draw() {
    
 		System.out.println("○"); 
 	} 
} 
public class Test {
    
 	public static void main(String[] args) {
    
 		IShape shape = new Rect(); 
 		shape.draw(); 
 	} 
}
  1. 使用 interface 定义一个接口
  2. 接口中的方法一定是抽象方法,因此可以省略 abstract
  3. 接口中的方法一定是 public,因此可以省略 public
  4. Cycle 使用 implements 继承接口,此时表达的含义不再是 “扩展”,而是 “实现”
  5. 在调用的时候同样可以创建一个接口的引用,对应到一个子类的实例
  6. 接口不能被单独实例化

扩展(extends) vs 实现(implements)
扩展指的是当前已经有一定的功能了,进一步扩充功能
实现指的是当前啥都没有,需要从头构造出来

接口中只能包含抽象方法,对于字段来说,接口中只能包含静态常量(final static)

interface IShape {
    
 	void draw(); 
 	public static final int num = 10; 
}

其中的public,static,final的关键字都可以省略,省略后的num仍然表示public的静态常量

提示:

  1. 我们创建接口的时候,接口的命名一般以大写字母 I 开头
  2. 接口的命名一般使用 “形容词” 词性的单词
  3. 阿里编码规范中约定,接口中的方法和属性不要加任何修饰符号,保持代码的简洁性

错误的代码

interface IShape {
    
 	abstract void draw() ; // 即便不写public,也是public 
} 
class Rect implements IShape {
    
 	void draw() {
    
 		System.out.println("□") ; //权限更加严格了,所以无法覆写。
 	} 
}

在这里插入图片描述

2.2 实现多个接口

有的时候我们需要让一个类同时继承自多个父类,这件事情在有些编程语言通过 多继承 的方式来实现的

然而 Java 中只支持单继承,一个类只能 extends 一个父类,但是可以同时实现多个接口,也能达到多继承类似的效果,这也就是为什么我们以后会常常用到接口

现在我们通过类来表示一组动物

class Animal {
    
 	protected String name; 
 
 	public Animal(String name
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值