JavaSE继承基本使用

网友投稿 456 2022-05-29

【JavaSE】继承基本使用

1. 为什么需要继承

2. 继承基本介绍和示意图

3. 继承的基本语法

4. 快速入门案例

5. 继承给编程带来的便利

6. 继承的深入讨论/细节问题

7. 继承的本质分析(重要)

8. 练习

1. 为什么需要继承

2. 继承基本介绍和示意图

3. 继承的基本语法

4. 快速入门案例

5. 继承给编程带来的便利

6. 继承的深入讨论/细节问题

7. 继承的本质分析(重要)

8. 练习

1. 为什么需要继承

一个小问题,还是看个程序[com.xdr630.extend_包: Extends01.java],提出代码复用的问题。

编写了两个类,一个是Pupil类(小学生),一个是Graduate(大学毕业生).

package com.xdr630.extends_; public class Pupil { public String name; public int age; private double score; public void setScore(double score) { this.score = score; } public void testing(){ System.out.println("小学生 " + name + " 正在考小学数学.."); } public void showInfo(){ System.out.println("学生名 " + name + " 年龄" + age + " 成绩" + score); } }

package com.xdr630.extends_; public class Graduate { public String name; public int age; private double score; public void setScore(double score) { this.score = score; } public void testing(){ System.out.println("大学生 " + name + " 正在考大学数学.."); } public void showInfo(){ System.out.println("学生名 " + name + " 年龄" + age + " 成绩" + score); } }

package com.xdr630.extends_; public class Extends01 { public static void main(String[] args) { Pupil pupil = new Pupil(); pupil.name = "小明"; pupil.age = 10; pupil.setScore(60); pupil.showInfo(); System.out.println("====================="); Graduate graduate = new Graduate(); graduate.name = "大明"; graduate.age = 23; graduate.setScore(100); graduate.showInfo(); } }

问题:两个类的属性和方法有很多是相同的,怎么办?

=>继承(代码复用性~)

2. 继承基本介绍和示意图

继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。

继承的示意图

3. 继承的基本语法

4. 快速入门案例

对 Extends01.java 改进,使用继承的方法,请注意体会使用继承的好处

package com.xdr630.extends_.improve_; // 父类,是 Pupil 和 Graduate 的父类 public class Student { //共有属性 public String name; public int age; private double score; //共有方法 public void setScore(double score) { this.score = score; } }

package com.xdr630.extends_.improve_; public class Pupil extends Student{ public void testing(){ System.out.println("小学生 " + name + " 正在考小学数学.."); } }

package com.xdr630.extends_.improve_; public class Graduate extends Student{ public void testing(){ System.out.println("大学生 " + name + " 正在考大学数学.."); } }

package com.xdr630.extends_.improve_; import com.xdr630.extends_.Graduate; import com.xdr630.extends_.Pupil; public class Extends01 { public static void main(String[] args) { com.xdr630.extends_.Pupil pupil = new Pupil(); pupil.name = "小明"; pupil.age = 10; pupil.setScore(60); pupil.showInfo(); System.out.println("====================="); com.xdr630.extends_.Graduate graduate = new Graduate(); graduate.name = "大明"; graduate.age = 23; graduate.setScore(100); graduate.showInfo(); } }

5. 继承给编程带来的便利

代码的复用性提高了

代码的扩展性和维护性提高了

6. 继承的深入讨论/细节问题

子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问。

Base 父类

package com.xdr630.extends_; public class Base { //父类 //4个属性 public int n1 = 100; protected int n2 = 200; int n3 = 300; private int n4 = 400; //父类提供一个public方法,返回了n4 public int getN4() { return n4; } public Base(){ System.out.println("Base()...."); } public void test100() { System.out.println("test100"); } protected void test200() { System.out.println("test200"); } void test300() { System.out.println("test300"); } private void test400() { System.out.println("test400"); } public void callTest400(){ test400(); } }

Sub 子类

package com.xdr630.extends_; //输入ctrl + H 可以看到类的继承关系 public class Sub extends Base { //子类 public Sub() {//无参构造器 System.out.println("子类Sub()构造器被调用...."); } public void sayOk() {//子类方法 //非私有的属性和方法可以在子类直接访问 //但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问 System.out.println(n1 + " " + n2 + " " + n3); test100(); test200(); test300(); //通过父类提供公共的方法去访问 System.out.println("n4=" + getN4()); //通过父类提供公共的方法去访问 callTest400(); } }

ExtendsDetail 测试类

package com.xdr630.extends_; public class ExtendsDetail { public static void main(String[] args) { Sub sub = new Sub(); sub.sayOk(); } }

子类必须调用父类的构造器, 完成父类的初始化

public class Base { //父类 public Base(){ System.out.println("父类Base()构造器被调用...."); } }

public class Sub extends Base { //子类 public Sub() {//无参构造器 //默认调用父类的无参构造方法 //super(); System.out.println("子类Sub()构造器被调用...."); } }

public class ExtendsDetail { public static void main(String[] args) { Sub sub = new Sub(); } }

当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。

当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器

public class Base { //父类 public Base(){ System.out.println("父类Base()构造器被调用...."); } }

public class Sub extends Base { //子类 public Sub() { System.out.println("子类Sub()构造器被调用...."); } public Sub(String name){ System.out.println("子类Sub(String name)构造器被调用...."); } }

public class ExtendsDetail { public static void main(String[] args) { Sub sub = new Sub(); System.out.println("===第二个对象==="); Sub sub2 = new Sub("jack"); } }

如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。

public class Base { //父类 public Base(String name,int age){//有参构造器 System.out.println("父类Base(String name,int age)构造器被调用...."); } }

public class Sub extends Base { //子类 public Sub(String name){ super("tom",30); System.out.println("子类Sub(String name)构造器被调用...."); } }

public class ExtendsDetail { public static void main(String[] args) { System.out.println("===第一个对象==="); Sub sub = new Sub(); System.out.println("===第二个对象==="); Sub sub2 = new Sub("jack"); } }

如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)

public class Base { //父类 public Base(String name,int age){//有参构造器 System.out.println("父类Base(String name,int age)构造器被调用...."); } }

public class Sub extends Base { //子类 public Sub(String name){ super("tom",30); System.out.println("子类Sub(String name)构造器被调用...."); } }

public class ExtendsDetail { public static void main(String[] args) { System.out.println("===第三个对象==="); Sub sub3 = new Sub("mike"); } }

super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)

super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

java 所有类都是 Object 类的子类, Object 是所有类的基类.

父类构造器的调用不限于直接父类,将一直往上追溯直到 Object 类(顶级父类)

子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。

思考:如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】

不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系

7. 继承的本质分析(重要)

看一个案例来分析当子类继承父类,创建子类对象时,内存中到底发生了什么? 提示:当子类对象创建好后,建立查找的关系。

public class ExtendsTheory { public static void main(String[] args) { Son son = new Son();//内存的布局 //-> 这时请大家注意,要按照查找关系来返回信息 //(1) 首先看子类是否有该属性 //(2) 如果子类有这个属性,并且可以访问,则返回信息 //(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..) //(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到Object... System.out.println(son.name);//返回就是大头儿子 System.out.println(son.getAge());//返回的就是39 System.out.println(son.hobby);//返回的就是旅游 } } class GrandPa { //爷类 String name = "大头爷爷"; String hobby = "旅游"; } class Father extends GrandPa {//父类 String name = "大头爸爸"; private int age = 39; public int getAge() { return age; } } class Son extends Father { //子类 String name = "大头儿子"; }

子类创建的内存布局

8. 练习

案例 1 ExtendsExercise01.java

public class ExtendsExercise01 { public static void main(String[] args) { B b = new B();//a , b name, b } } class A { A() { System.out.println("a"); } A(String name) { System.out.println("a name"); } } class B extends A { B() { this("abc"); System.out.println("b"); } B(String name) { //默认有 super(); System.out.println("b name"); } }

main中:B b = new B(); 会输出什么?

案例 2 ExtendsExercise02.java

public class ExtendsExercise02 { public static void main(String[] args) { C c = new C(); } } class A {//A类 public A() { System.out.println("我是A类"); } } class B extends A { //B类,继承A类 public B() { System.out.println("我是B类的无参构造"); } public B(String name) { System.out.println(name + "我是B类的有参构造"); } } class C extends B { //C类,继承 B类 public C() { this("hello"); System.out.println("我是c类的无参构造"); } public C(String name) { super("hahah"); System.out.println("我是c类的有参构造"); } }

main方法中: C c = new C(); 输出么内容?

案例 3 ExtendsExercise03.java

编写 Computer 类,包含 CPU、内存、硬盘等属性,getDetails 方法用于返回 Computer 的详细信息

编写 PC 子类,继承 Computer 类,添加特有属性【品牌 brand】

编写 NotePad 子类,继承 Computer 类,添加特有属性【color】

编写 Test 类,在 main 方法中创建 PC 和 NotePad 对象,分别给对象中特有的属性赋值,以及从 Computer 类继承的属性赋值,并使用方法并打印输出信息

public class Computer { private String cpu; private int memory; private int disk; public Computer(String cpu, int memory, int disk) { this.cpu = cpu; this.memory = memory; this.disk = disk; } //返回Computer信息 public String getDetails() { return "cpu=" + cpu + " memory=" + memory + " disk=" + disk; } public String getCpu() { return cpu; } public void setCpu(String cpu) { this.cpu = cpu; } public int getMemory() { return memory; } public void setMemory(int memory) { this.memory = memory; } public int getDisk() { return disk; } public void setDisk(int disk) { this.disk = disk; } }

public class PC extends Computer{ private String brand; public PC(String cpu, int memory, int disk, String brand) { super(cpu, memory, disk); this.brand = brand; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public void printInfo() { System.out.println("PC信息="); System.out.println(getDetails() + " brand=" + brand); } }

public class ExtendsExercise03 { public static void main(String[] args) { PC pc = new PC("intel", 16, 500, "IBM"); pc.printInfo(); } }

Java

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:如何降低软件复杂性?让代码更加精简
下一篇:墨天轮评测:GaussDB(for Redis)大Key操作的影响
相关文章