Java实战之继承与多态

类的继承以及抽象类的定义和使用

任务描述

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

相关知识
继承的概念

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

生活中的继承:


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

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

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

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

class 父类 {
    ...
}
class 子类 extends 父类 {
    ...
}

继承的特性

子类拥有父类非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 关键字来定义抽象类。切记,抽象类不能实例化对象,只能先定义一个非抽象子类继承该抽象类,再通过这个子类实例化对象。

public abstract class ClassName {
    ...
}

抽象方法

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

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

public abstract class ClassName {
    public abstract returnType methodName();
}

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

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

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

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

将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;
    }
    @Override
    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;
    }
    @Override
    public double getAcreage() {
        return length*width;
    }
}

super关键字与this关键字的使用

任务描述

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

相关知识
super关键字

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

class People {
    People(String name, int age) {   //父类构造方法
        this.name = name;
        this.age = age;
    }
    private String name;
    private int age;
}
class Student extends People {
    Student(String name, int age, String studentNumber) {   //子类构造方法
        super(name, age);   //调用父类构造方法
        this.studentNumber = studentNumber;   //继续完成子类自身的构造方法
    }
    private String studentNumber;
}

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

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

super.methodName();

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

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

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

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

使用构造方法初始化类。
在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 *********/

多态的理解和使用

任务描述

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

相关知识
多态

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

在这里插入图片描述

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

多态的优点:


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

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

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

例如:

class Parent {
    public void introduction() {
        ...
    }
}
class Child extends Parent {
    public void introduction() {
        ...
    }
}
public class Main {
    public static void main(String[] args) {
        Parent person = new Child();   //父类引用指向子类对象
        person.introduction();   //执行的是Child类的introduction方法
    }
}

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

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

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

评测说明

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

以下是测试样例:

测试输入:

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

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 *********/
  • 17
    点赞
  • 107
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮皮皮皮皮皮皮卡乒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值