首页 > 技术文章 > Educoder-Java程序开发基础-继承与多态(一)

junun 2021-07-18 12:24 原文

第1关:继承:实现代码复用

​ 本关任务:生活中的继承无处不在,请你通过继承Person类定义一个子类(派生类)Student类

class Person{
	String name;
	int age;
	//构造方法
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	void eat() {
		System.out.println("我会吃饭!");
	}
	void walk() {
		System.out.println("我会走路!");
	}
	//显示人的信息
	void showInfo() {
		System.out.println("姓名:"+name);
		System.out.println("年龄:"+age);
	}
}
class Student extends Person{
	String major;
	//构造方法
	public Student(String name,int age,String major){
		//使用super调用父类构造方法,对继承的姓名和年龄属性进行初始化
		super(name,age);
		
		this.major = major;
	}
	void Study() {
		System.out.println("我必须刻苦学习!");
	}
	//定义显示专业信息方法showMajor()
	void showMajor(){					
		System.out.println("专业:"+major);	
	}
    /*void showInfo(){
    super.showInfo();
    System.out.println("专业:"+major);
    }*/
}
public class ExtendsTest {

	public static void main(String[] args) {
		// 创建一个学生对象,姓名为张三,年龄为19,专业为计算机科学与技术
		Student s = new Student("张三",19,"计算机科学与技术");               ;
		//显示对象s的个人信息和专业
		s.showInfo();
		s.showMajor();		//用了super.showInfo()就不用这句
		s.Study();
	}
}

第2关:super关键字

​ 小明公司的老板非常抠门,他要求Salary类要继承Employee类,以减小后期对系统的维护成本。小明感觉无从下手,便请你来帮忙

import java.util.Scanner;

//请完善Employee类的定义
class Employee {
    private String name;
    private String birth;
    private String position;
    public Employee(String name,String birth,String position) {
        this.name=name; this.birth=birth; this.position=position;

    }
    //显示员工信息
    public void introduction() {
        System.out.print("员工姓名:"+name+" 出生年月:"+birth+" 职位:"+position);

    }
}
class Salary extends Employee {
    private double salary;
    public Salary(String name,String birth,String position,double salary) {
        //调用父类Employee构造方法
        super(name,birth,position);
        this.salary = salary;
    }
    public void introduction() {
        //调用父类Employee的成员方法introduction()
        super.introduction();
        System.out.println(" 薪水:"+salary);
        //程序员 薪水:4500.0
    }
}
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();
    }
}

第3关:继承方法的重定义(覆盖)

​ 本关任务:子类Teacher需要对从父类Person继承来的方法walk()和showInfo()进行重新定义

package step3;

class Person{
	String name;
	int age;
	//构造方法
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	void eat() {
		System.out.println("我会吃饭!");
	}
	void walk() {
		System.out.println("我会走路!");
	}
	//显示人的信息
	void showInfo() {
		System.out.println("姓名:"+name);
		System.out.println("年龄:"+age);
	}
}
class Teacher extends Person{
	String depart; //系部
	String course; //讲授课程
	//构造方法
	public Teacher(String name,int age,String depart,String course){
		//使用super调用父类构造方法,对继承的姓名和年龄属性进行初始化
		super(name,age);
		this.depart=depart; this.course=course;
		
	}
	//定义新的方法work()
	void work() {
		System.out.println("我讲授课程:"+course);
	}
	//对继承的walk()方法进行覆盖(重定义)
	void walk() {
		System.out.println("我走起路来挺像老师的!");
	}
	//对继承的showInfo()方法进行覆盖(重定义)
	void showInfo() {
		super.showInfo();
		System.out.println("部门:"+depart);
		System.out.println("讲授课程:"+course);
		
	}
}
public class OverloadTest {
	public static void main(String[] args) {
		// 创建一个教师对象,姓名为黄晓明,年龄为35,部门为计算机科学与技术,讲授课程为面向对象程序设计
		Teacher t = new Teacher("黄晓明",35,"计算机科学与技术","面向对象程序设计");
		//显示对象s的个人信息和专业
		t.walk();
		t.showInfo();
	}
}


第4关:访问控制(类的访问控制和类成员访问控制)

​ 本关任务:掌握如何通过访问控制修饰符来实现类的访问控制和类成员的访问控制

import myPackage.*;
public class AccessTest {
	public static void main(String[] args) {
		//创建一个雇员对象a
		Employee a = new Employee("张三",5000);
		//基本工资提高50%
		a.raiseSalary(50);
		a.showInfo();
		//创建一个经理对象b
		Manager b = new Manager("李四",10000,"经理",6000);
		//基本工资提高20%
		b.raiseSalary(20);
		b.showInfo();
	}
}

package myPackage;
//通过适当的修饰词确保Manager类能够被其他包访问
public class Manager extends Employee {
	//声明position、bonus属性为私有成员
	private String position;
	private double bonus; //奖金
	public Manager(String name,double baseSalary,String position,double bonus) {
		//调用基类构造方法
		super(name,baseSalary); 
		this.position = position;
		this.bonus = bonus;		
	}
	public double getSalary() {
		
		//经理工资=基本工资+奖金
		return super.getSalary()+bonus;
	}
	public void showInfo() {
		System.out.println("姓名:"+name);
		System.out.println("职位:"+position);
		System.out.println("工资:"+getSalary());
	}
}
package myPackage;
//通过适当的修饰词确保Employee类能够被其他包访问
public class Employee {
	//声明name属性为受保护成员,baseSalary属性为私有成员
	protected String name;
	private double baseSalary; //基本工资
	public Employee(String name,double baseSalary) {
		this.name = name;
		this.baseSalary = baseSalary;
	}
	////声明方法成员getSalary()为受保护成员
	protected double getSalary() {
		return baseSalary; 
	}
	public void raiseSalary(double byPercent) {
		double raise = baseSalary*byPercent/100;
		baseSalary += raise;
	}
	public void showInfo() {
		System.out.println("姓名:"+name);
		System.out.println("工资:"+baseSalary);
	}
}


第5关:子类实例化时构造代码块和构造方法的调用顺序

​ 本关任务:掌握在创建子类对象时父类和子类的构造代码块及构造方法的调用顺序

//派生类(子类)实例化时构造方法、构造代码块的调用次序
//静态代码块在程序构造时出现,即最早出现。其次是父类到子类按顺序出现
class Base {
	//父类静态代码块--1
	static {
		System.out.println("父类静态代码块!");
	}
	//父类构造代码块--3
	{
		System.out.println("父类构造代码块!");
	}
	
	
	//父类构造方法--4
	public Base() {
		System.out.println("父类构造方法!");
	}
}
class Derived extends Base {
	//派生类静态代码块--2
	static{
		System.out.println("派生类静态代码块!");
	}
	
	
	//派生类构造代码块--5
	{
		System.out.println("派生类构造代码块!");
	}
	//派生类构造函数--6
	{
		System.out.println("派生类构造方法!");
	}
	
	
}
public class InstantiateTest {

	public static void main(String[] args) {
		//创建一个派生类对象
		Derived obj = new Derived();
	}

}

第6关:final关键字的应用

​ 本关任务:掌握关键字final的应用

package step6;
import java.util.Scanner;
//如果定义为final class T,则这个类T不能被继承
class T { 
	// 任务点1:声明数据成员name为final数据成员
	final String name="张三丰";
	int age;	
	//任务点2:修改下列代码
	public T(/*String name,*/int age) {
		//this.name = name;
		this.age = age;
	}
	//任务点3:对showName()方法加上适当修饰符,使其不能在派生类中重定义
	final void showName() { 
		System.out.println("我是行不改名坐不改姓的"+this.name);
	}
	void showInfo() {
		System.out.println("姓名:"+this.name);
		System.out.println("年龄:"+this.age);
	}
}
class TT extends T {
	String position;
	public TT(String name,int age,String position) {
		super(/*name,*/age);
		this.position = position;
		
	}
	// 任务点4:能否重定义void showName()?如果不能请屏蔽相关代码
	/*(void showName() {		
		System.out.println("我的名字是"+name);
	}*/
	void showInfo() {
		super.showInfo();
		System.out.println("职位:"+this.position);		
	}
}
public class FinalTest {
	public static void main(String[] args) {
		String name,position;
		int age;
		Scanner input = new Scanner(System.in);
		name = input.next();
		age = input.nextInt();
		position = input.next();
		TT obj = new TT(name,age,position);
		obj.showName();
		obj.showInfo();
	
	}
}

第7关:抽象类与多态 - Shape的烦心事

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

抽象方法
package step7;

import java.util.Scanner;

/********** Begin *********/
abstract class Shape {
	abstract public double getArea();

}

class Circle extends Shape {
    private double radius;
    public Circle(double){
        this.radius=radius;
    }
    public double getArea(){
        return radius*radius*Math.PI;
    }
  
}

class Rectangle extends Shape {
    private double length;
    private double width;
    public Rectangle(double length,double width){
        this.length=length;
        this.width=width;
    }
    public double getArea(){
        return length*width;
    }
}
/********** End *********/
public class AbstractTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        double radius = scanner.nextDouble();
        Circle circle = new Circle(radius);
        double length = scanner.nextDouble();
        double width = scanner.nextDouble();        
        Rectangle rectangle = new Rectangle(length, width);
        System.out.printf("%10.4f\n",circle.getArea());
        System.out.printf("%10.4f\n",rectangle.getArea());
    }
}

第8关:接口和多态 - 阿猫阿狗

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

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

  • 继承抽象类或实现接口
  • 对抽象类或接口中定义的抽象方法进行重写
  • 父类(或接口)引用指向子类对象

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

package step8;

//接口定义
interface Ianimal{
	//定义三个方法,eat(),work()和cry(),接口中的方法都没有具体实现
	public void eat();
	public void work();
	public void cry();
}

class Dog implements Ianimal{
	//在具体类中需要对接口中的方法进行具体实现
	public void eat(){
		System.out.println("吃骨头!");
	}
	public void work(){
		System.out.println("看家!");
	}
	public void cry(){
		System.out.println("汪汪汪!");
	}
}
class Cat implements Ianimal{
	//在具体类中需要对接口中的方法进行具体实现
	public void eat(){
		System.out.println("吃鱼!");
	}
	public void work(){
		System.out.println("抓老鼠!");
	}
	public void cry(){
		System.out.println("喵喵喵!");
	}
}
public class InterfaceTest {
	public static void main(String[] args) {
		//同样的消息根据引用a指向不同的对象会调用不同类中的相应方法
		Ianimal a = new Dog();
		a.eat();
		a.work();
		a.cry();
		a  = new Cat();
		a.eat();
		a.work();
		a.cry();		
	}
}

第9关:继承和接口实现混合示例

​ 老猴子具有爬树的能力,小猴子不仅继承了老猴子的爬树的能力,还具有了游泳和飞翔的能力。下面需要请你通过继承和接口实现来定义小猴子类

• 子类可以通过extends关键字在父类的基础上进行定义。

• 子类可以从父类继承相关属性和方法,也可以新定义自己的属性和方法,即子类可以对父类进行扩展。

• 另外子类可以通过实现某些接口扩展自己的方法(功能)

package step9;

import java.util.Scanner;

//飞翔功能接口
interface iFly{
	public void flying();
}
//游泳功能接口
interface iSwim {
	public void swimming();
}
//定义老猴子类OldMonkey
class OldMonkey{
  String name;
  public OldMonkey(String name){
      this.name = name;
  }
  public void climbing(){
      System.out.println(name+"会爬树");
  }
}
//定义新猴子类NewMonkey,它继承OldMonkey,并实现iFly,iSwim接口
class NewMonkey extends OldMonkey implements iFly,iSwim{
	public NewMonkey(String name) {
		super(name);
	}
	//接口方法具体实现
    public void flying(){
		System.out.println(name+"学会了飞翔");
    }
    public void swimming(){
		System.out.println(name+"学会了游泳");
    }
}
public class MonkeyTest {

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		String name = input.next();
		NewMonkey m = new NewMonkey(name);
		m.climbing();
		m.swimming();
		m.flying();
	}
}

推荐阅读