快捷搜索:  汽车  科技

java如何实现面向对象的设计(Java教程之代码的发展之路)

java如何实现面向对象的设计(Java教程之代码的发展之路)我将这些类当中 [共性] 或者说是 [相同] 的内容 抽取到一个父类 (Employee 员工 ) 当中 再让 Coder 和 Manager 继承 Employee 代码就不需要重复编写了 这就能够提高代码的复用性了 ~所以 这时候我要用继承来优化代码了聊到这个地方 很多同学就在想 我为什么让我的类与类之间建立这种关系呢 ? 请同学们先阅读下方代码假设 我要编写一款 xxx 公司的人员管理系统 这款管理系统需要对项目经理和程序员的信息做管理 所以就需要编写如下两个类现在大家可以发现 这两个类中的东西 完全是长一样的 !!! 那我将来要是再多一个 Hr 的类 对人事的信息做管理 这些重复的代码 岂不是要再写一遍 ? 麻烦 !

前言 :

Hello 各位同学朋友大家好啊 今天给大家分享的技术呢 是面向对象三大特征之一的继承 .

我们今天主要按照以下几个点 展开继承的讲解

目录 :
  • 继承的介绍
  • 继承的好处和弊端
  • 继承中成员访问特点 - 成员变量
  • 继承中成员访问特点 - 成员方法
    • 方法重写
  • 继承中成员访问特点 - 构造方法
  • this 和 super 关键字
1. 继承的介绍

提到了继承 大家想到了什么 ? 是的 子女继承到的家产 那家产是存在着一种关系的 父亲和儿子的关系 .

对比生活中的继承 Java 中的继承 其实就是让类与类之间产生关系 什么关系 ? 子父类关系 当这种关系建立起来之后 子类就可以直接使用父类中 非私有的成员了.

聊到这个地方 很多同学就在想 我为什么让我的类与类之间建立这种关系呢 ? 请同学们先阅读下方代码

假设 我要编写一款 xxx 公司的人员管理系统 这款管理系统需要对项目经理和程序员的信息做管理 所以就需要编写如下两个类

java如何实现面向对象的设计(Java教程之代码的发展之路)(1)

现在大家可以发现 这两个类中的东西 完全是长一样的 !!! 那我将来要是再多一个 Hr 的类 对人事的信息做管理 这些重复的代码 岂不是要再写一遍 ? 麻烦 !

所以 这时候我要用继承来优化代码了

我将这些类当中 [共性] 或者说是 [相同] 的内容 抽取到一个父类 (Employee 员工 ) 当中 再让 Coder 和 Manager 继承 Employee 代码就不需要重复编写了 这就能够提高代码的复用性了 ~

java如何实现面向对象的设计(Java教程之代码的发展之路)(2)

但是 代码层面 我给如何让 Coder 和 Manager 继承 Employee 呢 ? 请同学们继续看继承的格式

继承的格式 :

java如何实现面向对象的设计(Java教程之代码的发展之路)(3)

可以看到 实现继承 我们是通过 Extends 关键字进行编写的 下面我们编写下代码

  • 示例代码 :

class Employee { String name; int age; double salary; } class Coder extends Employee { } class Manager extends Employee { } public class Test { public static void main(String[] args) { Coder c = new Coder(); c.name = "张三"; c.age = 23; c.salary = 12000; System.out.println(c.name "---" c.age "---" c.salary); Manager m = new Manager(); m.name = "李四"; m.age = 24; m.salary = 18000; System.out.println(m.name "---" m.age "---" m.salary); } }

通过上面的代码 同学们可以发现 Coder 和 Manager 中 明明什么都没写 但是却能够访问到父类 Employee 中的属性了

所以 重复的代码就不需要重复编写 代码的复用性就提高了 ~

但是 我相信有些同学可能会想

Q : 按照标准 JavaBean 来说 成员变量不应该私有化吗 ? 那如果父类中的成员私有了 子类岂不是用不到这些数据了.

A : 能想到这个问题非常好 说明之前的知识掌握的很扎实 但是继续想 我们私有成员变量之后 会提供对应的 set 和 get 方法吧 这些set \ get 可都是公共的 子类是可以继承到直接用的

  • 示例代码 :

package com.itheima.myextends; class Employee { private String name; private int age; private double salary; public Employee() { } public Employee(String name int age double salary) { this.name = name; this.age = age; this.salary = salary; } 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 double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } } class Coder extends Employee { } class Manager extends Employee { } public class Test { public static void main(String[] args) { Coder c = new Coder(); c.setName("张三"); c.setAge(23); c.setSalary(12000); System.out.println(c.getName() "---" c.getAge() "---" c.getSalary()); Manager m = new Manager(); m.setName("李四"); m.setAge(24); m.setSalary(18000); System.out.println(m.getName() "---" m.getAge() "---" m.getSalary()); } } 2. 继承的好处和弊端好处 :

通过上面的代码 同学们感受到继承的什么好处了啊 ? 是的 非常明显的发现 代码的复用性提高了.

除此之外呢 继承还可以提高代码的维护性 这什么意思 ?

假设 我要在这款管理系统中 加入一个 id 的属性 那使用继承前 我就需要在每一个类中 挨个编写 但是现在有了继承后 我只需要在父类中编写一个 id 所有的子类 是不是就都具备了这个属性了 ? 是的 ! 这就提高了代码的维护性了 !

java如何实现面向对象的设计(Java教程之代码的发展之路)(4)

弊端 :

继续刚刚的思路 同学们可能会想 增加一个 所有子类都有了 那删除一个 岂不是所有子类都没有了啊...

这不就牵一发而动全身了嘛... 是的 这就是继承的弊端 类的耦合性太强了.

java如何实现面向对象的设计(Java教程之代码的发展之路)(5)

何时使用继承 :

聊到现在 大家发现继承有好处 也有弊端 那该如何设计 才能让利大于弊呢 ?

  • 正确示例 :

java如何实现面向对象的设计(Java教程之代码的发展之路)(6)

  • 错误示例 :

java如何实现面向对象的设计(Java教程之代码的发展之路)(7)

3. 继承中成员变量访问特点
  • 思考:子父类中,如果出现了重名的成员变量,使用的时候会优先使用??

java如何实现面向对象的设计(Java教程之代码的发展之路)(8)

  • 运行效果 :

20

  • 原因 :

java如何实现面向对象的设计(Java教程之代码的发展之路)(9)

一定要使用父类的 可以使用 super 关键字进行区分

这里同学们可以先建立起一个使用思路

  • this. 调用本类成员
  • super.调用父类成员

public class Zi extends Fu { int num = 20; public void method(){ System.out.println(super.num); } }

java如何实现面向对象的设计(Java教程之代码的发展之路)(10)

4. 继承中成员方法访问特点
  • 思考:子类继承了父类之后,是否可以自己继续定义方法?
  • 回答:当然可以 子类继承父类 是可以在继承到父类成员之后 继续加东西的

java如何实现面向对象的设计(Java教程之代码的发展之路)(11)

  • 问题 : 那子父类中 要是出现了重名的成员 逻辑却不一样呢 ?

public class Fu { public void method() { // 父类的方法 System.out.println("父类method..."); } } class Zi extends Fu { public void method() { System.out.println("子类method..."); } }

  • 运行结果 :

子类method...

  • 结论 :
  • 子父类中如果出现了重名的成员方法,优先使用子类的方法 但这其实是子类方法对父类方法进行了重写
方法重写 Override :

先跟大家聊聊什么是方法重写 在继承体系中,子类可以继承到父类的方法 但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改 这就需要采用方法的重写,方法重写又称方法覆盖

java如何实现面向对象的设计(Java教程之代码的发展之路)(12)

class Fu { public void catch(){ System.out.println("使用弓箭捉羊..."); } } class Zi extends Fu { @Override public void catch(){ System.out.println("使用98Kar狙击枪捉羊..."); } }

  • 注意事项 :

java如何实现面向对象的设计(Java教程之代码的发展之路)(13)

解释 :

父类中私有的方法 子类访问不到 就更不能重写了

子类重写父类方法 可以理解为是对功能进行增强 那如果允许把访问权限降低 那岂不是功能越做越差了嘛

Java 中继承的特点 :

了解了 Java 中方法重写后 我们再来说下 Java 中继承的特点

  • 特点 : Java只支持单继承,不支持多继承,但支持多层继承
    • 其实就是说 一个类 最多只能有一个父类 不能同时有多个父类
  • class A {}

    class B {}

    class C extends A B {} // 编译出错
    • 为什么 ? 因为担心逻辑冲突

java如何实现面向对象的设计(Java教程之代码的发展之路)(14)

  • 问题 : 那多层继承呢 ?
5. 继承中构造方法的访问特点
  • 思考问题 : 父类的构造方法 子类能不能继承到呢 ?
  • 回答 : 不允许 因为构造方法要求 方法名和类名必须相同 如果子类继承到父类的构造方法 那方法名和类名就不一致了
  • 结论 : 子类不能继承父类的构造方法 将来子类的构造方法 需要自己编写

public Fu { public Fu(){} } class Zi extends Fu { public Fu(){} // 如果子类继承到父类的构造方法 那方法名和类名就不一致了 }继承中构造方法的访问流程

  • 阅读代码材料 :

public class Test { public static void main(String[] args) { Zi z1 = new Zi(); Zi z2 = new Zi(10); } } class Fu { public Fu() { System.out.println("Fu类空参构造方法"); } public Fu(int num) { System.out.println("Fu类带参数构造方法"); } } class Zi extends Fu { public Zi() { System.out.println("Zi类空参数构造方法"); } public Zi(int num) { System.out.println("Zi类带参数构造方法"); } }

  • 运行效果 :

Fu类空参构造方法 Zi类空参数构造方法 Fu类空参构造方法 Zi类带参数构造方法

通过打印效果同学们可以看出 我们无论通过子类的哪一个构造方法创建对象 都会执行到 Fu类的空参构造方法

为什么 ? 因为在子类的构造方法 第一行代码 系统会默认帮我们加入 super ();

通过super() 在访问父类的构造方法 现在我们手动把 super(); 加上 同学们再阅读下试试吧~

public class Test { public static void main(String[] args) { Zi z1 = new Zi(); Zi z2 = new Zi(10); } } class Fu { public Fu() { System.out.println("Fu类空参构造方法"); } public Fu(int num) { System.out.println("Fu类带参数构造方法"); } } class Zi extends Fu { public Zi() { super(); System.out.println("Zi类空参数构造方法"); } public Zi(int num) { super(); System.out.println("Zi类带参数构造方法"); } }

okk 看懂了执行流程之后 新的问题来了 我们知道学习这个细节 对代码有什么帮助呢 ?

答案是 : 子类将来可以把一部分数据 交给父类初始化了

我们来看一段代码

public class Person { private String name; private int age; public Person() { } public Person(String name int age) { this.name = name; this.age = 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 class Student extends Person { private double score; public Student() { } public Student(String name int age double score) { super(name age); this.score = score; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } public void study() { System.out.println( "姓名为" super.getName() " 年龄为" super.getAge() " 成绩为" score "分的学生 正在学习Java"); } }

public class ExtendsTest2 { public static void main(String[] args) { Student stu = new Student("李四" 24 100); stu.study(); } }

在上述代码中 我们可以发现 main方法中 创建学生对象 我们给了 3个参数 先执行子类的带参数构造方法

其中前两个数据 我们通过super 交给了父类初始化 最后一个成绩数据 父类没有 子类自己完成了初始化

public Student(String name int age double score) { // "李四" 24 100 super(name age); // "李四" 24 交给父类 this.score = score; // 100 子类自己初始化 }

配合一张内存图 大家再看一下

java如何实现面向对象的设计(Java教程之代码的发展之路)(15)

这里我们可以发现 堆内存的对象中 会存在一个 super 区域 专门存放父类的成员

所以 前两个数据 父类中有 就交给父类初始化 最后一个数据 父类没有 子类就自己完成初始化.

6. this 和 super

上述文章中 我们其实关于 this 和 super 做了很多使用了 接下来我们来梳理下

  • this:代表本类对象的引用
  • super:代表父类存储空间的标识(可以理解为父类对象引用)

java如何实现面向对象的设计(Java教程之代码的发展之路)(16)

好啦 本次关于继承的技术 就跟大家聊到这里了

我们下次再见 ~

掰掰~ (^▽^)

猜您喜欢: