封装、继承和多态进阶(三)

本文通过实例详细介绍了Java面向对象编程中的继承、重写、多态和封装概念,包括继承的原理、特性、关键字,重写和重载的区别,以及抽象类、接口和封装的应用。
摘要由CSDN通过智能技术生成
任务描述

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

相关知识

为了完成本关任务,我们通过一个实例来一步一步总结归纳Java面向对象的知识。

 
  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{}

输出结果: -----testsuper---- Animal(int) Dog() Animal() Dog(int) -----testoverride----- Animal() Animal(int) Dog() 动物可以移动 狗可以跳墙

编程要求

教练和运动员案例:

  • 乒乓球运动员和篮球运动员;

  • 乒乓球教练和篮球教练;

  • 跟乒乓球相关的人员都需要学习英语;

  • 分析,这个案例中有哪些抽象类,哪些接口,哪些具体类。

分析过程如下:

- 具体输出要求请看测试说明。

测试说明

测试输入: 张继科 30 易建联 31 刘国梁 42 杜锋 37 预期输出: 张继科---30 人都是要睡觉的 乒乓球运动员吃大白菜,喝小米粥 乒乓球运动员学习如何发球和接球 乒乓球运动员说英语

----------------

易建联---31 人都是要睡觉的 篮球运动员吃牛肉,喝牛奶 篮球运动员学习如何运球和投篮

----------------

刘国梁---42 人都是要睡觉的 乒乓球教练吃小白菜,喝大米粥 乒乓球教练教如何发球和接球 乒乓球教练说英语

----------------

杜锋---37 人都是要睡觉的 篮球教练吃羊肉,喝羊奶 篮球教练教如何运球和投篮

----------------


package case3;

import java.util.Scanner;

public class Task3 {
	public static void main(String[] args) {
		@SuppressWarnings("resource")
		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 *********/
    void speak();
	/********* end *********/
}

// 定义人的抽象类Person 封装name和age
// 无参构造函数
// 有参构造函数初始化name和age
// 定义具体方法sleep() 输出'人都是要睡觉的'
// 抽象方法eat()(吃的不一样)
abstract class Person {
	/********* begin *********/
    private String name;
    private int age;
    public String getname(){
        return name;
    }
    public void setname(String name){
        this.name=name;
    }
    public int getage(){
        return age;
    }
    public void setage(int age){
        this.age=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);
        name=super.getname();
        age=super.getage();
    }
    abstract void study();
	/********* end *********/
}

// 定义教练Coach(抽象类)继承自Person类
// 无参构造函数
// 有参构造函数初始化name和age
// 教练教的不一样 定义抽象方法teach()
abstract class Coach extends Person {
	/********* begin *********/
    public Coach(String name,int age){
        super(name,age);
        name=super.getname();
        age=super.getage();
    }
    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);
        name=super.getname();
        age=super.getage();
    }
    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);
        name=super.getname();
        age=super.getage();
    }
    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);
        name=super.getname();
        age=super.getage();
    }
    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);
        name=super.getname();
        age=super.getage();
    }
    public void eat(){
        System.out.println("篮球教练吃羊肉,喝羊奶");
    }
    public void teach(){
        System.out.println("篮球教练教如何运球和投篮");
    }
	/********* end *********/
}


  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

STM32单片机定制

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

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

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

打赏作者

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

抵扣说明:

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

余额充值