Java头歌 3.2 Java语言之继承与多态

第1关:类的继承以及抽象类的定义和使用 - Shape的烦心事

任务描述

我们都知道,生活中的继承无处不在,在数学王国的领域也是如此。最近数学王国中一位名叫Shape的父亲有一个烦心事,他有两个儿子Circle和Rectangle,这两个儿子比较叛逆,虽然Sharp苦口婆心的教育他们说要继承自己的方法,但他们觉得没有父亲也能计算自己的面积。无奈之下Shape找到了你,请你来编写程序告诉他的两个儿子要继承他的方法。

相关知识
继承的概念

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。

生活中的继承: 

  • 兔子和羊属于食草动物类,狮子和豹属于食肉动物类。
  • 食草动物和食肉动物又都属于动物类。

如果在程序设计中不使用继承,则可能造成代码存在重复,导致代码量大且臃肿,以至于维护性不高,因为后期需要修改重复代码段时,就需要修改大量代码,容易出错。

所以要从根本上解决这个问题,就需要继承,将多段代码中相同的部分提取出来组成一个父类。

类的继承格式

在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:

 
  1. class 父类 {
  2. ...
  3. }
  4. class 子类 extends 父类 {
  5. ...
  6. }
继承的特性
  • 子类拥有父类非private的属性和方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法,即重写父类的方法。
  • Java的继承是单继承,但是可以多重继承。单继承就是一个子类只能继承一个父类;多重继承就是,例如A类继承B类,B类继承C类,所以按照关系就是C类是B类的父类,B类是A类的父类,这是Java继承区别于C++继承的一个特性。
访问控制的继承

请注意以下方法继承的规则:

  • 父类中声明为 public 的方法在子类中也必须为 public。
  • 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
  • 父类中声明为 private 的方法,不能够被继承。
final关键字

final 关键字声明类可以把类定义为不能被继承,即“最终”的类;如果用于修饰方法,则该方法不能被子类重写。

注:实例变量也可以被定义为 final 类型,被定义为 final 类型的变量不能被修改。被声明为 final 的类的方法会被自动声明为 final 类型,但是其实例变量并不是 final 类型。

抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

在Java语言中使用 abstract 关键字来定义抽象类。切记,抽象类不能实例化对象,只能先定义一个非抽象子类继承该抽象类,再通过这个子类实例化对象

 
  1. public abstract class ClassName {
  2. ...
  3. }
抽象方法

如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。

abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。

 
  1. public abstract class ClassName {
  2. public abstract returnType methodName();
  3. }

声明抽象方法会造成以下两个结果:

  • 如果一个类包含抽象方法,那么该类必须是抽象类。
  • 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。

继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。

编程要求

本关的编程任务是补全右侧代码片段中BeginEnd中间的代码,具体要求如下:

  • 将Shape类定义为抽象类,Shape类的getAcreage()方法(获取面积)定义为抽象方法。
  • 将Circle类和Rectangle类定义为Shape类的子类,分别重写Shape类的抽象方法getAcreage(),返回各自的面积。
  • PI取3.1415926.

特别注意:由于类型精度的问题,计算圆的面积的时候,请使用 PI * r * r

评测说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是测试样例:

测试输入: 2 2 3 预期输出: 12.5663704 6.0

package step1;

import java.util.Scanner;

public class ShapeTrouble {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        double radius = scanner.nextDouble();
        double length = scanner.nextDouble();
        double width = scanner.nextDouble();
        Circle circle = new Circle(radius);
        Rectangle rectangle = new Rectangle(length, width);
        System.out.println(circle.getAcreage());
        System.out.print(rectangle.getAcreage());
    }
}

abstract class Shape {
     abstract  double getAcreage();
}

 class Circle extends Shape {
    double radius;
    double pi=3.1415926;
    public Circle(double radius){
        this.radius=radius;
    }

    public  double getAcreage() {
    return pi*radius*radius;  
    }
}

class Rectangle extends Shape {
    double length;
    double width;
    public Rectangle(double length,double width){
        this.length=length;
        this.width=width;
    }

    public double getAcreage() {
        return length*width;
    }
}

第2关:super关键字与this关键字的使用 - 系统升级

任务描述

小明工作的公司最近要升级系统了,原先的员工管理系统有一个Employee类用于管理员工的姓名、出生年月、职位等个人信息,现在老板希望新增加一个Salary类用于管理员工的工资。小明公司的老板非常抠门,他要求Salary类要继承Employee类,以减小后期对系统的维护成本。小明感觉无从下手,便请你来帮忙。

相关知识
super关键字

对于继承父类的子类而言,有时我们需要在子类中访问父类的方法,此时便可以使用 super 关键字,请看下面这个示例:

 
  1. class People {
  2. People(String name, int age) { //父类构造方法
  3. this.name = name;
  4. this.age = age;
  5. }
  6. private String name;
  7. private int age;
  8. }
  9. class Student extends People {
  10. Student(String name, int age, String studentNumber) { //子类构造方法
  11. super(name, age); //调用父类构造方法
  12. this.studentNumber = studentNumber; //继续完成子类自身的构造方法
  13. }
  14. private String studentNumber;
  15. }

在上面这个例子中,父类People有自身的构造方法,当子类Student继承People类时,显然我们不希望将父类的构造方法在子类中再实现一遍,否则就是代码冗余,此时便在子类的构造方法中先使用super()来调用父类构造方法,然后再根据实际需求完成子类自身的构造方法。

如果是访问父类的成员方法,则格式为:

 
  1. super.methodName();

super关键字与this关键字的总结:

  • super:通过super关键字来实现对父类成员的访问,用来引用当前的类的父类。
  • this:指向当前的类的引用。

同学们要灵活运用这两个关键字,以实现不同的需求。

编程要求

本关的编程任务是补全右侧代码片段中BeginEnd中间的代码,具体要求如下:

  • 使用构造方法初始化类。
  • 在Salary类使用super关键字调用父类的方法。
  • 定义introduction方法介绍员工信息,格式见测试样例。
评测说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是测试样例:

测试输入: 张三 1995.07 程序员 4500 预期输出: 员工姓名:张三 出生年月:1995.07 职位:程序员 薪水:4500.0

注:各项之间用空格隔开,冒号使用中文字符。

package step2;

import java.util.Scanner;

public class SystemUpdate {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String name = scanner.next();
        String birth = scanner.next();
        String position = scanner.next();
        double salary = scanner.nextDouble();
        Salary employee = new Salary(name, birth, position, salary);
        employee.introduction();
    }
}

/********** Begin *********/
class Employee {
    String name;
    String birth;
    String position;
    public Employee(String name,String birth,String position) {
	    	this.name=name;
	    	this.birth=birth;
	    	this.position=position;
	    }
}

class Salary extends Employee {
    private double salary;
    Salary(String name,String birth,String position,double salary){
	    	super(name,birth,position);
	    	this.salary=salary;
	    }
	    public void introduction() {
	    	System.out.println("员工姓名:"+name+" "+"出生年月:"+birth+" "+"职位:"+position+" "+ "薪水:"+salary);
	    }
}
/********** End *********/

第3关:多态的理解和使用 - 阿猫阿狗

任务描述

小明新学习了多态的概念,老师布置作业要编写一个小程序,用多态的概念实现对猫和狗的介绍。可惜小明学艺不精,只好请你来帮忙。

相关知识
多态

多态就是同一个方法,使用不同的实例而执行不同操作,如图所示: 

同样是打印这一个方法,如果对象是彩色打印机,则打印出来的是彩色文件;如果对象是黑白打印机,则打印出来的是黑白文件。多态是对象多种表现形式的体现。

多态的优点:

  • 消除类型之间的耦合关系
  • 可替换性
  • 可扩充性
  • 接口性
  • 灵活性
  • 简化性

多态存在的三个必要条件:

  • 继承
  • 重写
  • 父类引用指向子类对象

例如:

 
  1. class Parent {
  2. public void introduction() {
  3. ...
  4. }
  5. }
  6. class Child extends Parent {
  7. public void introduction() {
  8. ...
  9. }
  10. }
  11. public class Main {
  12. public static void main(String[] args) {
  13. Parent person = new Child(); //父类引用指向子类对象
  14. person.introduction(); //执行的是Child类的introduction方法
  15. }
  16. }

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

编程要求

本关的编程任务是补全右侧代码片段中BeginEnd中间的代码,具体要求如下:

  • 使用多态的方式调用对象成员方法。
  • 依次输出猫吃的东西、猫做的事情、狗吃的东西、狗做的事情,格式见测试样例。
评测说明

平台将自动编译补全后的代码,并生成若干组测试数据,接着根据程序的输出判断程序是否正确。

以下是测试样例:

测试输入:

预期输出: 吃鱼 抓老鼠 吃骨头 看家

package step3;

public class CatAndDog {
    public static void main(String[] args) {
        /********** Begin *********/
        Animal cat=new Cat();
	    Animal dog=new Dog();
        /********** End *********/
        cat.eat();
        cat.work();
        dog.eat();
        dog.work();
    }
}

abstract class Animal {
    abstract void eat();
    abstract void work();
}

/********** Begin *********/
class Cat extends Animal {
    public void eat() {
			System.out.println("吃鱼");
	   }
	public void work() {
			System.out.println("抓老鼠");
	   }
}

class Dog extends Animal {
    public void eat() {
			System.out.println("吃骨头");
	   }
		public void work() {
			System.out.println("看家");
	   }
}
/********** End *********/

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值