抽象类

每一个技术的出现, 都是为了解决某一种问题的.

抽象类的出现, 就是为了让子类强制重写父类中的某一个方法.

父类的抽象方法在子类中必须重写, 否则子类代码直接报错.

抽象方法所在的类就叫做抽象类.

抽象类和抽象方法主要学习:

  1. 抽象类的定义格式.

  2. 抽象方法的定义格式.

  3. 子类继承抽象类之后, 如何重写抽象方法.

  4. 抽象类在实际开发中的意义所在.

将多个子类中的共的行为 (方法) 抽取到父类之后, 由于每一个子类的执行的内容是不一样的, 所以父类中不能确定具体的方法体, 则该方法可以被定义为抽象方法.

如果一个类里面存在抽象方法, 不管有多少个, 那么这个类就必须被定义为抽象类.

抽象方法是不写方法体的, 直接用分号结束, 连花括号都没有. 抽象方法的定义格式为: public abstract 返回值类型 方法名 (参数列表);

抽象类的定义格式为: public abstract class 类名 { 类体 }

程序示例:

public abstract class Person {
public abstract void work();
}

抽象类不能实例化 (实例化即创建对象). 如果可以实例化, 则抽象类的对象可以调用抽象类的方法, 包括抽象方法, 而抽象方法没有方法体, 那么调用什么呢?由此就产生了矛盾, 因此规定抽象类不能实例化.

抽象类中不一定有抽象方法, 但是有抽象方法的类一定是抽象类.

抽象类可以有构造方法. 既然抽象类不能实例化, 那么抽象类的构造方法有何作用? 作用: 当其子类创建对象时, 可以给子类对象赋值. 子类的构造方法用 super 调用父类的构造方法. 抽象类的构造方法是给可以实例化的子类通过 super() 来使用的.

抽象类的子类要么重写抽象类的所有抽象方法, 要么子类本身也是一个抽象类. 如果子类还是抽象类, 那么这个子类还是不能实例化, 如果想创建对象, 那就要再定义 "孙子类", 且一定不是抽象类, 那么这个 "孙子类" 还是要重写全部的抽象方法. 所以一般都是采用第一种方法, 即在子类中重写全部的抽象方法.

也就是说, 一般情况下, 抽象类的子类不是抽象类.

程序示例:

public abstract class Person { // 是抽象类但是没有抽象方法
// public abstract void work();
public void sleep() {
}
}
public class Person { // 有抽象方法但不是抽象类, 则报错
public abstract void work();
public void sleep() {
}
}
public abstract class Person { // 带有构造方法的抽象类
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void work();
public void sleep() {
}
}

练习:
编写带有抽象类的标准 Javabean 类
青蛙 Frog: 属性: 名字, 年龄 行为: 吃虫子, 喝水
狗 Dog: 属性: 名字, 年龄 行为: 吃骨头, 喝水
山羊 Sheep: 属性: 名字, 年龄 行为: 吃草, 喝水

画出示意图:


图 1

Javabean 类:

public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void drink() {
System.out.println(getName() + "在喝水. ");
}
public abstract void eat();
}
public class Dog extends Animal {
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗在吃骨头. ");
}
}
public class Frog extends Animal {
public Frog() {
}
public Frog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("青蛙在吃虫子. ");
}
}
public class Sheep extends Animal {
public Sheep() {
}
public Sheep(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("羊在吃草. ");
}
}

测试类:

public class Test {
public static void main(String[] args) {
Frog f = new Frog("小绿", 1);
System.out.println(f.getName() + ", " + f.getAge());
f.eat();
f.drink();
}
}

执行结果:

小绿, 1
青蛙在吃虫子.
小绿在喝水.

在父类中定义抽象类, 在子类中又重写, 看起来是很麻烦, 因为在父类中多写了一个类, 但是这样做是有意义的, 因为假如有多个人去调用这个父类写了多个子类, 如果没有这个抽象类限制了子类中的这个类的书写形式, 那么不同的人所写的子类中的这个方法可能差别很大, 另外的人去调用时, 不知道该如何调用, 如果在父类中写了这个抽象类, 就相当于限定了这个类的形式, 调用时如果不知道如何调用, 只需要去父类中看看就知道了. 所以, 父类中定义抽象类有统一形式的意义.

抽象的子类的父类不一定是抽象的, 可能子类特有的方法是抽象方法.

posted @   有空  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示