1. 抽象类概念
定义一个类时,常常需要定义一些成员方法用于描述类的行为特征,但有时这些方法的实现方式是无法确定的。例如,Animal类中的shout()方法用于描述动物的叫声,但是不同的动物,叫声也不相同,因此在shout()方法中无法准确描述动物的叫声。
针对上面描述的情况,Java提供了抽象方法来满足这种需求。抽象方法是使用abstract关键字修饰的成员方法,抽象方法在定义时不需要实现方法体。抽象方法的语法格式如下。
public abstract 返回值类型 方法名称(参数); //抽象方法,无方法体
当一个类包含了抽象方法,该类就是抽象类。抽象类和抽象方法一样,必须使用abstract关键字进行修饰。抽象类的语法格式如下。
public abstract class 抽象类名称 {
public abstract 返回值类型 抽象方法名称(参数); //抽象方法,无方法体
}
2. 抽象类的规则
从上面抽象类的语法格式中可以发现,抽象类的定义比普通类多了一个或多个抽象方法,其他地方与普通类的组成基本相同。抽象类的定义规则如下。
(1)包含抽象方法的类必须是抽象类。
(2)声明抽象类和抽象方法时都要使用abstract关键字修饰。
(3)抽象方法只需声明而不需要实现。
(4)如果非抽象类继承了抽象类,那么该类必须实现抽象类中的全部抽象方法。
3. 抽象类案例
-
案例需求
定义抽象类动物类Animal,定义其抽象方法shout(),抽象方法用public修饰。
定义一个小猫类Cat,继承Animal抽象类,在Cat类中覆盖Animal类中的抽象方法shout(),输出“小猫喵喵叫”。
定义一个小狗类Dog,继承Animal抽象类,在Dog类中覆盖Animal类中的抽象方法shout(),输出“小狗汪汪叫”。
编写测试类,使用无参构造方法实现Cat类和Dog类的实例化,访问shout()方法。
-
抽象类Animal类
public abstract class Animal {
public abstract void shout();
}
-
Cat类
public class Cat extends Animal{
@Override
public void shout() {
System.out.println("小猫喵喵叫");
}
}
-
Dog类
public class Dog extends Animal{
@Override
public void shout() {
System.out.println("小狗汪汪叫");
}
}
-
测试类
public class TestCat {
@Test
public void test(){
Cat cat = new Cat();
cat.shout();
}
}
4. 练习1
定义抽象类图形类Shape,定义其抽象方法getArea(),抽象方法用public修饰。
定义一个圆形类Circle,继承Shape抽象类,在Circle类中定义一个double型的表示半径的成员变量radius,成员变量用private修饰,定义成员变量的getter和setter方法;在Circle中覆盖Shape类中的抽象方法getArea()。
定义一个正方形类Square,继承Shape抽象类,在Square类中定义一个double型的表示边长的成员变量r,成员变量用private修饰,定义成员变量的getter和setter方法;在Square中覆盖Shape类中的抽象方法getArea()。
编写测试类,使用无参构造方法实现Circle类和Square类的实例化,访问getArea()方法。
-
抽象类Shape类
public abstract class Shape {
public abstract double getArea();
}
-
Circle类
public class Circle extends Shape{
private double radius;
public void setRadius(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
-
Square类
public class Square extends Shape{
private double r;
public void setR(double r) {
this.r= r;
}
public double getR() {
return r;
}
@Override
public double getArea() {
return r*r;
}
}
-
测试类
public class TestDemo {
@Test
public void test(){
Circle c = new Circle();
c.setRadius(2);
double area = c.getArea();
System.out.println("圆的面积是:" + area);
}
@Test
public void test2(){
Square s = new Square();
s.setR(2);
double area = s.getArea();
System.out.println("正方形的面积是:" + area);
}
}
5. 练习2
案例需求
定义抽象类消费卡Card,定义其抽象方法折扣double getDiscount(),抽象方法用public修饰。
定义一个金卡GoldCard,继承Card抽象类,在GoldCard类中定义一个double型的表示价格的成员变量price,成员变量用private修饰,定义成员变量的getter和setter方法;在GoldCard中覆盖Card类中的抽象方法double getDiscount(),返回原价格的八折。
定义一个银卡SilverCard,继承Card抽象类,在SilverCard类中定义一个double型的表示价格的成员变量price,成员变量用private修饰,定义成员变量的getter和setter方法;在SilverCard中覆盖Card类中的抽象方法double getDiscount(),如果价格满100元则按原价格的九折,否则按原价。
编写测试类,使用无参构造方法实现GoldCard类和SilverCard类的实例化,访问getDiscount()方法。
- 抽象类Card类
public abstract class Card{
public abstract double getDiscount();
}
- GoldCard类
public class GoldCard extends Card{
private double price;
public void setPrice(double price) {
this.price = price;
}
public double getPrice() {
return price;
}
@Override
public double getDiscount() {
return price * 0.8;
}
}
- SilverCard类
public class SilverCard extends Card{
private double price;
public void setPrice(double price) {
this.price = price;
}
public double getPrice() {
return price;
}
@Override
public double getDiscount() {
if(price >= 100){
return price * 0.9;
}else{
return price;
}
}
}
- 测试类
public class TestDemo {
@Test
public void test(){
GoldCard gold = new GoldCard();
gold.setPrice(100);
double price = gold.getDiscount();
System.out.println("金卡的折扣价格为:" + price);
}
@Test
public void test2(){
SilverCard silver = new SilverCard();
silver.setPrice(80);
double price = silver.getDiscount();
System.out.println("银卡的折扣价格为:" + price);
silver.setPrice(100);
price = silver.getDiscount();
System.out.println("银卡的折扣价格为:" + price);
}
}
6. 思考
自定义抽象类,定义其抽象方法,抽象方法用public修饰。
自定义非抽象子类,继承抽象类,覆盖抽象类中的抽象方法。
编写测试类,使用无参构造方法实现非抽象子类的实例化,访问重写方法。