Java面向对象 - 封装、继承和多态的综合练习

第1关:封装、继承和多态进阶(一)

任务描述

本关任务:按要求编写一个Java应用程序,巩固Java面向对象知识。

package case1;

import java.util.Scanner;

public class Task1 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String dogName = sc.next();
		String dogSex = sc.next();
		String dogColor = sc.next();
		String catName = sc.next();
		String catSex = sc.next();
		double catWeight = sc.nextDouble();
		// 通过有参构造函数实例化Dog类对象dog
		// dog调用talk()方法
		// dog调用eat()方法
		/********* begin *********/
		Dog chs=new Dog();
        chs.setDog(dogName,dogSex,dogColor);
        chs.talk();
        chs.eat();
		/********* end *********/
		// 通过有参构造函数实例化Cat类对象cat
		// cat调用talk()方法
		// cat调用eat()方法
		/********* begin *********/
		Cat jq=new Cat();
        jq.setCat(catName,catSex,catWeight);
        jq.talk();
        jq.eat();
		/********* end *********/
	}
}

// 抽象类Pet 封装属性name和sex
// 构造函数初始化name和sex
// 声明抽象方法talk()
// 声明抽象方法eat()
abstract class Pet {
	/********* begin *********/
    String name;
    String sex;
    public void setPet(String name,String sex){
        this.name=name;
        this.sex=sex;
    }
    abstract void talk();
    abstract void eat();
	/********* end *********/
}

// Dog类继承自Pet类 封装属性color
// 构造函数初始化name、sex和color
// 实现自己的talk()方法和eat()方法
// talk()输出'名称:name,性别:sex,颜色:color,汪汪叫'
// eat()输出'name吃骨头'
class Dog extends Pet {
	/********* begin *********/
	String color;
    public void setDog(String name,String sex,String color){
        this.color=color;
        super.setPet(name,sex);
    }

    public void talk(){
        System.out.println("名称:"+this.name+",性别:"+this.sex+",颜色:"+this.color+",汪汪叫");
    }

    public void eat(){
        System.out.println(this.name+"吃骨头!");
    }
	/********* end *********/
}

// Cat类继承自Pet类 封装属性weight
// 构造函数初始化name、sex和weight
// 实现自己的talk()方法和eat()方法
// talk()输出'名称:name,性别:sex,体重:weight kg,喵喵叫'
// eat()输出'name吃鱼'
class Cat extends Pet {
	/********* begin *********/
    double weight;
    public void setCat(String name,String sex,double weight){
        this.weight=weight;
        super.setPet(name,sex);
    }

    public void talk(){
        System.out.println("名称:"+this.name+",性别:"+this.sex+",体重:"+this.weight+"kg,喵喵叫");
    }

    public void eat(){
        System.out.println(this.name+"吃鱼!");
    }
	/********* end *********/
}

第2关:封装、继承和多态进阶(二)

任务描述

本关任务:按要求编写一个Java应用程序,巩固Java封装、继承和多态的知识。

package case2;

import java.util.Scanner;

public class Task2 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String cName = sc.next();
		String cSex = sc.next();
		int cAge = sc.nextInt();
		String eName = sc.next();
		String eSex = sc.next();
		int eAge = sc.nextInt();
		// 创建测试类对象test
		// 创建Person类对象person1,引用指向中国人,通过有参构造函数实例化中国人类对象
		// 通过showEat()方法调用Chinese的eat()方法
		// 创建Person类对象person2,引用指向英国人,通过有参构造函数实例化英国人类对象
		// 通过showEat()方法调用English的eat()方法
		/********* begin *********/
        Person st=new Chinese(cName,cSex,cAge);
        showEat(st);

        English chs=new English(eName,eSex,eAge);
        showEat(chs);
		/********* end *********/
		// 强制类型转换(向下转型) 调用Chinese类特有的方法shadowBoxing()
		// 强制类型转换(向下转型) 调用English类特有的方法horseRiding()
		/********* begin *********/
        Chinese st2=(Chinese)st;
        st2.shadowBoxing();

        English chs2=(English)chs;
        chs2.horseRiding();
		/********* end *********/
	}

	// 定义showEat方法,使用父类作为方法的形参,实现多态,传入的是哪个具体对象就调用哪个对象的eat()方法
	/********* begin *********/
    public static void showEat(Person p){
        p.eat();
    }
	/********* end *********/
}

// 抽象类Person 封装属性name、sex和age
// 构造函数初始化name、sex和age
// 声明抽象方法eat()
abstract class Person {
	/********* begin *********/
    abstract void eat();
    String name;
    String sex;
    int age;

    public void setPerson(String name,String sex,int age){
        this.name=name;
        this.sex=sex;
        this.age=age;
    }
	/********* end *********/
}

// Chinese类继承自Person类
// 构造函数初始化name、sex和age
// 重写父类方法eat() 输出'姓名:name,性别:sex,年龄:age,我是中国人,我喜欢吃饭!'
// 定义子类特有方法shadowBoxing(),当父类引用指向子类对象时无法调用该方法 输出'name在练习太极拳!'
class Chinese extends Person {
	/********* begin *********/
    public void eat(){
        System.out.println("姓名:"+this.name+",性别:"+this.sex+",年龄:"+this.age+",我是中国人,我喜欢吃饭!");
    }

    public Chinese(String name,String sex,int age){
        super.setPerson(name,sex,age);
    }
    
    public void shadowBoxing(){
        System.out.println(this.name+"在练习太极拳!");
    }
	/********* end *********/
}

// English类继承自Person类
// 构造函数初始化name、sex和age
// 重写父类方法eat() 输出'姓名:name,性别:sex,年龄:age,我是英国人,我喜欢吃三明治!'
// 定义子类特有方法horseRiding(),当父类引用指向子类对象时无法调用该方法 输出'name在练习骑马!'
class English extends Person {
	/********* begin *********/
    public void eat(){
        System.out.println("姓名:"+this.name+",性别:"+this.sex+",年龄:"+this.age+",我是英国人,我喜欢吃三明治!");
    }
    
    public English(String name,String sex,int age){
        super.setPerson(name,sex,age);
    }

    void horseRiding(){
        System.out.println(this.name+"在练习骑马!");
    }
	/********* end *********/
}

第3关:封装、继承和多态进阶(三)

任务描述

本关任务:通过一个简单实例讲解并自己动手编写一个Java应用程序,全面复习Java面向对象知识。

package case3;

import java.util.Scanner;

public class Task3 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String pppName = sc.next();
		int pppAge = sc.nextInt();
		String bpName = sc.next();
		int bpAge = sc.nextInt();
		String ppcName = sc.next();
		int ppcAge = sc.nextInt();
		String bcName = sc.next();
		int bcAge = sc.nextInt();
		// 测试运动员(乒乓球运动员和篮球运动员)
		// 乒乓球运动员
		// 通过带参构造函数实例化PingPangPlayer对象ppp
		// 输出'name---age'
		// 分别调用sleep()、eat()、study()、speak()方法
		/********* begin *********/
        PingPangPlayer ppp=new PingPangPlayer(pppName,pppAge);
        System.out.println(pppName+"---"+pppAge);
        ppp.sleep();
        ppp.eat();
        ppp.study();
        ppp.speak();
		/********* end *********/
		System.out.println("----------------");
		// 篮球运动员
		// 通过带参构造函数实例化BasketballPlayer对象bp
		// 输出'name---age'
		// 分别调用sleep()、eat()、study()方法
		/********* begin *********/
        BasketballPlayer bp=new BasketballPlayer(bpName,bpAge);
        System.out.println(bpName+"---"+bpAge);
        bp.sleep();
        bp.eat();
        bp.study();
		/********* end *********/
		System.out.println("----------------");
		// 测试教练(乒乓球教练和篮球教练)
		// 乒乓球教练
		// 通过带参构造函数实例化PingPangCoach对象ppc
		// 输出'name---age'
		// 分别调用sleep()、eat()、teach()、speak()方法
		/********* begin *********/
        PingPangCoach ppc=new PingPangCoach(ppcName,ppcAge);
        System.out.println(ppcName+"---"+ppcAge);
        ppc.sleep();
        ppc.eat();
        ppc.teach();
        ppc.speak();
		/********* end *********/
		System.out.println("----------------");
		// 篮球教练
		// 通过带参构造函数实例化BasketballCoach对象bc
		// 输出'name---age'
		// 分别调用sleep()、eat()、teach()方法
		/********* begin *********/
        BasketballCoach bc=new BasketballCoach(bcName,bcAge);
        System.out.println(bcName+"---"+bcAge);
        bc.sleep();
        bc.eat();
        bc.teach();
		/********* end *********/
		System.out.println("----------------");
	}
}

// 说英语接口 声明抽象方法speak()
interface SpeakEnglish {
	/********* begin *********/
    abstract void speak();
	/********* end *********/
}

// 定义人的抽象类Person 封装name和age
// 无参构造函数
// 有参构造函数初始化name和age
// 定义具体方法sleep() 输出'人都是要睡觉的'
// 抽象方法eat()(吃的不一样)
abstract class Person {
	/********* begin *********/
    String name;
    int age;

    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }

    public void sleep(){
        System.out.println("人都是要睡觉的");
    }

    abstract void eat();
	/********* end *********/
}

// 定义运动员Player(抽象类)继承自Person类
// 无参构造函数
// 有参构造函数初始化name和age
// 运动员学习内容不一样,抽取为抽象 定义抽象方法study()
abstract class Player extends Person {
	/********* begin *********/
    public Player(String name,int age){
        super(name,age);
    }

    abstract void study();
	/********* end *********/
}

// 定义教练Coach(抽象类)继承自Person类
// 无参构造函数
// 有参构造函数初始化name和age
// 教练教的不一样 定义抽象方法teach()
abstract class Coach extends Person {
	/********* begin *********/
    public Coach(String name,int age){
        super(name,age);
    }

    abstract void teach();
	/********* end *********/
}

// 定义乒乓球运动员具体类PingPangPlayer 继承自Player类并实现SpeakEnglish类(兵乓球运动员需要说英语)
// 无参构造函数
// 有参构造函数初始化name和age
// 实现自己的eat()方法 输出'乒乓球运动员吃大白菜,喝小米粥'
// 实现自己的study()方法 输出'乒乓球运动员学习如何发球和接球'
// 实现自己的speak()方法 输出'乒乓球运动员说英语'
class PingPangPlayer extends Player implements SpeakEnglish {
	/********* begin *********/
    public PingPangPlayer(String name,int age){
        super(name,age);
    }

    public void eat(){
        System.out.println("乒乓球运动员吃大白菜,喝小米粥");
    }

    public void study(){
        System.out.println("乒乓球运动员学习如何发球和接球");
    }

    public void speak(){
        System.out.println("乒乓球运动员说英语");
    }
	/********* end *********/
}

// 定义篮球运动员具体类BasketballPlayer 继承自Player类 不需要继承接口,因为他不需要说英语
// 无参构造函数
// 有参构造函数初始化name和age
// 实现自己的eat()方法 输出'篮球运动员吃牛肉,喝牛奶'
// 实现自己的study()方法 输出'篮球运动员学习如何运球和投篮'
class BasketballPlayer extends Player {
	/********* begin *********/
    public BasketballPlayer(String name,int age){
        super(name,age);
    }

    public void eat(){
        System.out.println("篮球运动员吃牛肉,喝牛奶");
    }

    public void study(){
        System.out.println("篮球运动员学习如何运球和投篮");
    }
	/********* end *********/
}

// 定义乒乓球教练具体类 PingPangCoach 继承自Coach类并实现SpeakEnglish类(兵乓球教练需要说英语)
// 无参构造函数
// 有参构造函数初始化name和age
// 实现自己的eat()方法 输出'乒乓球教练吃小白菜,喝大米粥'
// 实现自己的teach()方法 输出'乒乓球教练教如何发球和接球'
// 实现自己的speak()方法 输出'乒乓球教练说英语'
class PingPangCoach extends Coach implements SpeakEnglish {
	/********* begin *********/
    public PingPangCoach(String name,int age){
        super(name,age);
    }

    public void eat(){
        System.out.println("乒乓球教练吃小白菜,喝大米粥");
    }

    public void teach(){
        System.out.println("乒乓球教练教如何发球和接球");
    }

    public void speak(){
        System.out.println("乒乓球教练说英语");
    }
	/********* end *********/
}

// 定义篮球教练具体类BasketballCoach 继承自Coach类 不需要继承接口,因为他不需要说英语
// 无参构造函数
// 有参构造函数初始化name和age
// 实现自己的eat()方法 输出'篮球教练吃羊肉,喝羊奶'
// 实现自己的teach()方法 输出'篮球教练教如何运球和投篮'
class BasketballCoach extends Coach {
	/********* begin *********/
    public BasketballCoach(String name,int age){
        super(name,age);
    }

    public void eat(){
        System.out.println("篮球教练吃羊肉,喝羊奶");
    }

    public void teach(){
        System.out.println("篮球教练教如何运球和投篮");
    }
	/********* end *********/
}
  1. package test;
  2. /*知识点目录
  3. 1,Java继承
  4. 1.1 继承的概念
  5. 1.2 继承的特性
  6. 1.3 继承关键字
  7. 1.4 构造器
  8. 2,Java重写(Override)与重载(Overload)
  9. 2.1 重写(Override)
  10. 2.2 重载(Overload)
  11. 2.3 总结
  12. 3,Java多态
  13. 3.1 多态的实现方式
  14. 4,Java抽象类
  15. 5,Java封装
  16. 6,Java接口
  17. */
  18. /* 1.1继承的概念
  19. 继承在本职上是特殊——一般的关系,即常说的is-a关系。子类继承父类,表明子类是一种特殊的父类,并且具有父类所不具有的一些属性或方法。通过 extends 关键字可以声明一个类是从另外一个类继承而来的。
  20. */
  21. /* 1.2继承的特性
  22. 1).子类拥有父类非private的属性,方法;
  23. 2).子类可以拥有自己的属性和方法,即子类可以对父类进行扩展;
  24. 3).子类可以用自己的方式实现父类的方法;
  25. 4).Java的继承是单继承,这是Java继承区别于C++继承的一个特性;
  26. 5).提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系)。
  27. */
  28. /* 1.3继承关键字
  29. 1).使用 extends 和 implements 来实现继承,所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承Object;
  30. 2).一个子类只能拥有一个父类,所以 extends 只能继承一个类;
  31. 3).使用 implements 关键字变相的使Java具有多继承的特性,为类继承接口,可以同时继承多个接口;
  32. 4).通过super关键字来实现对父类成员的访问,用来引用当前对象的父类;
  33. 5).final 关键字
  34. 5.1) 声明类则把类定义为不能继承的,即最终类;修饰方法,则该方法不能被子类重写;定义实例变量,则变量不能被修改;
  35. 5.2) final 类的方法自动为 final方法,但实例变量不自动是 final变量。
  36. */
  37. interface A{}
  38. interface B{}
  39. class Animal{
  40. public void move(){
  41. System.out.println("动物可以移动");
  42. }
  43. Animal(){
  44. System.out.println("Animal()");
  45. }
  46. Animal(int n){
  47. System.out.println("Animal(int)");
  48. }
  49. }
  50. final class Dog extends Animal implements A,B {
  51. final String name = "旺财";
  52. final public void finalFun(){
  53. }
  54. /* 2.1.1 重写(Override)
  55. 1).重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写;
  56. 2).重写的好处在于子类可以根据需要,定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法;
  57. 3).重写方法不能抛出新的检查异常或者比被重写方法声明更加宽泛的异常。
  58. */
  59. public void move(){
  60. System.out.println("狗可以跳墙");
  61. }
  62. /*2.2.1重载(Overload)
  63. 1).重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同;
  64. 2).每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
  65. */
  66. public void move(int n){
  67. System.out.println("这只狗可以跳"+n+"米的墙");
  68. }
  69. public String toString() {
  70. //1.3.1 通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
  71. return "I am a Dog " + super.toString();
  72. }
  73. /* 1.4 构造器
  74. 1).子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表;
  75. 2).如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。
  76. */
  77. Dog(){
  78. super(300);
  79. System.out.println("Dog()");
  80. }
  81. Dog(int n){
  82. System.out.println("Dog(int)");
  83. }
  84. }
  85. class Test{
  86. static void testsuper(){
  87. System.out.println("-----testsuper----");
  88. new Dog();
  89. new Dog(1);
  90. }
  91. static void testoverride(){
  92. System.out.println("-----testoverride-----");
  93. Animal a = new Animal();
  94. Animal b = new Dog();
  95. a.move();
  96. /*2.1.2 重写(Override)
  97. 1).尽管b属于Animal类型,但是它运行的是Dog类的move方法;
  98. 2).在编译阶段,只是检查参数的引用类型。在运行时,Java虚拟机(JVM)指定对象的类型并且运行该对象的方法。
  99. */
  100. b.move();
  101. }
  102. }
  103. public class JavaDemo{
  104. public static void main(String[] args) {
  105. Test.testsuper();
  106. Test.testoverride();
  107. }
  108. }
  109. /* 2.1.3方法的重写规则
  110. 1).参数列表必须完全与被重写方法的相同;
  111. 2).返回类型必须完全与被重写方法的返回类型相同;
  112. 3).访问权限不能比父类中被重写的方法的访问权限更低;
  113. 4).父类的成员方法只能被它的子类重写;
  114. 5).声明为final的方法不能被重写;
  115. 6).声明为static的方法不能被重写,但是能够被再次声明;
  116. 7).子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法;
  117. 8).子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法;
  118. 9).重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常,但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以;
  119. 10).构造方法不能被重写;
  120. 11).如果不能继承一个方法,则不能重写这个方法。
  121. */
  122. /*2.2.2重载规则
  123. 1).被重载的方法必须改变参数列表(参数个数或类型或顺序不一样);
  124. 2).被重载的方法可以改变返回类型;
  125. 3).被重载的方法可以改变访问修饰符;
  126. 4).被重载的方法可以声明新的或更广的检查异常;
  127. 5).方法能够在同一个类中或者在一个子类中被重载;
  128. 6).无法以返回值类型作为重载函数的区分标准。
  129. */
  130. /*
  131. 重写与重载之间的区别
  132. 区别点 重载方法 重写方法
  133. 参数列表 必须修改 一定不能修改
  134. 返回类型 可以修改 一定不能修改
  135. 异常 可以修改 可以减少或删除,一定不能抛出新的或者更广的异常
  136. 访问 可以修改 一定不能做更严格的限制(可以降低限制)
  137. 总结
  138. 方法的重写和重载是Java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载是一类中多态性的一种表现。
  139. */
  140. /*访问控制修饰符
  141. Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java支持4种不同的访问权限。
  142. 默认的,也称为 default,在同一包内可见,不使用任何修饰符;
  143. 私有的,以 private 修饰符指定,在同一类内可见;
  144. 共有的,以 public 修饰符指定,对所有类可见;
  145. 受保护的,以 protected 修饰符指定,对同一包内的类和所有子类可见。
  146. 我们可以可以通过以下表来说明访问权限:
  147. 访问控制
  148. 修饰符 当前类 同一包内 子孙类 其他包
  149. public Y Y Y Y
  150. protected Y Y Y N
  151. default Y Y N N
  152. private Y N N N
  153. */
  154. /*3,Java多态
  155. 多态就是同一个接口,使用不同的实例执行不同操作。
  156. 3.1 多态的实现方式 重写、接口、抽象类和抽象方法。
  157. */
  158. /*4,Java抽象类
  159. 1).使用abstract class来定义抽象类,抽象类不能被实例化;
  160. 2).抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类;
  161. 3).抽象类中的抽象方法只是声明,不包含方法体;
  162. 4).构造方法,类方法(用static修饰的方法)不能声明为抽象方法;
  163. 5).任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
  164. */
  165. abstract class Employee{
  166. //抽象方法
  167. public abstract double computePay();
  168. }
  169. /*4.2继承抽象类
  170. */
  171. class Salary extends Employee{
  172. public double computePay(){
  173. return 0;
  174. }
  175. }
  176. /*
  177. 5,Java封装
  178. 封装(英语:Encapsulation)是指,一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。
  179. 封装的优点:
  180. 1).良好的封装能够减少耦合;
  181. 2).类内部的结构可以自由修改;
  182. 3). 可以对成员变量进行更精确的控制;
  183. 4). 隐藏信息,实现细节。
  184. 实现Java封装的步骤:
  185. 1). 修改属性的可见性来限制对属性的访问;
  186. 2).对每个值属性提供对外的公共方法访问。
  187. */
  188. /*
  189. 6,Java接口
  190. 1).接口,在Java编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明;
  191. 2).一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类;
  192. 3).接口不能包含成员变量,除了 static 和 final 变量;
  193. 4).接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract;
  194. 5).接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量;
  195. 6).接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法;
  196. 7).类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常;
  197. 8).类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型;
  198. 9).接口的继承使用extends关键字,允许多重继承,可能定义或继承相同的方法。
  199. */
  200. interface C extends A,B{}
  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值