11_Java中的继承
Java中的继承
一、继承概述
1、继承概述:
在类中:有一些类具有一些相同的属性和方法,即相同的一些特征。
继承是面向对象的三大特性之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义、追加属性和方法
2、继承格式:
格式:
public class 子类名 extends 父类名{} //extends 继承、扩展 //示例: public class Son extends Base{} //Son: 是子类,也称为派生类 //Base: 是父类,也称为基类,超类
3、继承中子类的特点:
子类可以有父类的内容
子类还可以有自己特有的内容
思考?当子类与父类中有同名属性和方法时,调用时如何区分?
二、继承的好处和弊端
1、继承的好处:
提高了代码的复用性(多个类相同的成员可以放到同一个类中)
提高了代码的维护性(如果方法需要修改,只用将父类修改既可)
2、继承的弊端:
继承让类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性
3、什么时候使用继承:
继承体现的关系:is a
假设法:我有两个类A和B,如果他们满足A是B的一种,或者B是A的一种,就说明他们之间存在继承关系,这个时候就可以考虑使用继承来实现,否则就不能滥用继承。
举例:苹果 和 水果,猫 和 动物
三、继承中变量访问的特点:
在子类的方法中访问一个变量时访问优先顺序是
1、子类局部范围(方法中)找
2、子类成员范围(本类中)找
3、父类成员范围(父类中)找
如果都没有就报错:注意这里只考虑到父亲,父亲以上不考虑
package com.itheima_02; /* 父类 */ public class Base { //成员变量 public int age = 40; //此处为了测试使用public权限 }
package com.itheima_02; /* 子类 */ public class Son extends Base{ //成员属性 public int height = 175; //身高 public int age = 20; //年龄 当子类中存在这个成员属性时会优先调用自己的 //show方法 public void show(){ int age = 30; //没有用this指针来指明是 又优先使用的方法里面的age变量 System.out.println(age); System.out.println(height); //报错 方法中找不到->本类中找不到->父类中也找不到 // System.out.println(weight); } }
package com.itheima_02; /* 测试类 */ public class Demo { public static void main(String[] args){ //创建对象,调用方法 Son s = new Son(); s.show(); } }
四、super关键字
1、super与this:
用于访问父类成员变量
在Java中貌似没有作用域的方法:
super关键字的用法和this关键字的用法相似
this:代表本类对象的引用
super:代表父类存储空间的标识(可以理解为父类对象引用)
2、两个关键字的使用:
关键字 | 访问成员变量 | 访问构造方法 (...表示参数) | 访问成员方法 |
---|---|---|---|
this | this.成员变量 访问本类成员变量 | this(...) 访问本类构造方法 | this.成员方法名(...) 访问成员方法 |
super | super.成员变量 访问父类成员变量 | super(...) 访问父类构造方法 | super.成员方法(...) 访问父类成员方法 |
3、参考代码:
package com.itheima_03; /* 父类 */ public class Base { public int age = 40; }
package com.itheima_03; /* 子类 */ public class Son extends Base{ public int age = 20; public void show(){ int age = 30; System.out.println(age); //需求,访问本类中的成员变量? this指针 System.out.println(this.age); //我要访问父类的成员变量? super System.out.println(super.age); } }
package com.itheima_03; /* 测试类 */ public class Demo { public static void main(String[] args){ //创建对象,调用方法 Son s = new Son(); s.show(); } }
4、参考(看着玩就行):
//C++中可以通过作用域 来区分调用 子类、父类、方法中 同名变量 的位置 #include <iostream> using namespace std; class Base { public: int age = 40; }; class Son :public Base { public: int age = 20; public: void show() { int age = 10; //调用父类 cout << Base::age << endl; //调用子类 cout << Son::age << endl; //或者cout<<this->age<<endl; //调用方法中的变量 cout << age << endl; } }; int main() { Son s; s.show(); system("pause"); return 0; }
五、继承中构造方法的访问特点:
理解提示:先有父亲 才能 有你,所以父类先要初始化
1、子类中的所有的构造方法默认都会访问父类中无参构造方法
为什么?
1、因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化
2、每一个子类构造方法的第一条语句默认都是:super() -> 表示调用父类构造函数 括号中无参数所以都是访问的父类无参构造
2、父类中没有无参构造方法,只有带参构造方法 或者说 我们想要先调用的是父类中的有参构造方法
1、通过修改默认语句:super(); 为 super(参数列表); 来解决这两个问题
2、如果只是前者,我们推荐补全父类无参构造
3、参考代码:
package com.itheima_04; /* 父类 */ public class Base { public Base(){ System.out.println("父类无参构造方法被调用"); } public Base(int age){ System.out.println("父类有参构造方法被调用"); } }
package com.itheima_04; /* 子类 */ public class Son extends Base{ public Son(){ // super(); 默认存在可以不写 // 如果 需要调用父类中的带参构造方法(或者父类无无参构造:写了有参没写无参)就 使用带参语句super(参数列表); super(10); System.out.println("子类无参构造方法被调用"); } public Son(int age){ // super(); 默认存在可以不写 super(10); //如果 需要调用父类中的带参构造方法就 使用带参语句super(参数列表); System.out.println("子类有参构造方法被调用"); } }
package com.itheima_04; /* 测试类 */ public class Demo { public static void main(String[] args) { //创建对象 Son s = new Son(); //可以发现先调用了父类的无参构造 Son s2 = new Son(10); } }
六、继承中成员方法的访问特点
通过子类对象访问一个方法
1、子类范围找
2、父类范围找
如果还没找到就报错(同变量,不考虑父亲的父...)
package com.itheima_05; /* 父类 */ public class Base { public Base(){}; public void show(){ System.out.println("父类中show方法的调用"); } }
package com.itheima_05; /* 子类 */ public class Son extends Base{ public Son(){}; public void method(){ System.out.println("子类中method方法的调用"); } public void show(){ super.show(); System.out.println("子类中show方法被调用"); } }
package com.itheima_05; /* 测试类 */ public class Demo { public static void main(String[] args){ //创建对象调用方法 Son s = new Son(); s.method(); s.show(); } }
总结:继承中的成员(包括方法和属性)由子类创建对象进行(同名成员)调用时是由近到远来寻找,也可以通过this与super关键字来直接限定调用和使用;而对于构造方法会通过默认语句调用父类无参,也可以通过修改默认语句调用有参构造方法
七、super内存图:
略...
八、方法重写
一、方法重写的概述:
1、方法重写概述:
子类中出现了和父类中一摸一样的方法声明
2、方法重写的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容
3、练习手机类和新手机类:
@Override
是一个注释(注解后面会学习到)
可以帮助我们检查重写方法的方法声明的正确性
二、方法重写注意事项:
1、私有方法不能被重写(父类私有成员子类是不能继承的)
2、子类方法的访问权限不能更低(public > 默认 > private)
3、参考代码:
package com.itheima_07; /* 父类 */ public class Base { private void show(){ System.out.println("父类中show()方法被调用"); } void method(){ System.out.println("父类中method()方法被调用"); } }
package com.itheima_07; /* 子类 */ public class Son extends Base{ //子类不能继承父类中的 私有内容 /* @Override private void show(){ System.out.println("子类中show()方法被调用"); }*/ /* @Override public void method(){ System.out.println("父类中method()方法被调用"); }*/ @Override public void method(){ //当不提供访问权限修饰符时 默认提供一个 System.out.println("父类中method()方法被调用"); } }
九、Java中继承的注意事项
1、Java中类只支持单继承,不支持多继承
2、Java中类支持多层继承
3、参考代码:
package com.itheima_08; public class Granddad { public void drink(){ System.out.println("爷爷爱喝酒"); } }
package com.itheima_08; public class Father extends Granddad{ public void NoSmoke(){ System.out.println("爸爸不爱抽烟"); } }
package com.itheima_08; public class Mother { public void dance(){ System.out.println("妈妈爱跳舞"); } }
package com.itheima_08; /* 在Java中不支持多继承 public class Son extends Father, Mother{ }*/ public class Son extends Father{ }
十、继承案例
1、老师学生:
需求:先定义一个老师类和一个学生类,再抽取这两个类中的共性内容创建一个父类
package com.itheima_10; /* 人类 */ public class Person { private String name; private int age; public Person(){}; public Person(String name, int age){ this.name = name; this.age = age; } public void setName(String name){ this.name = name; } public String getName(){ return this.name; } public void setAge(int age){ this.age = age; } public int getAge(){ return age; } }
package com.itheima_10; /* 学生类 */ public class Student extends Person{ //添加构造方法 public Student(){}; public Student(String name, int age){ // this.name = name; // this.age = age; super(name, age); } public void study(){ System.out.println("好好学习,天天向上"); } }
package com.itheima_10; /* 老师类 */ public class Teacher extends Person{ public Teacher(){} //手动提供了无参构造,因为下面有有参构造 public Teacher(String name, int age){ //此处无法访问父类的私有权限 // this.name = name; // this.age = age; super(name, age); } public void teach(){ System.out.println("用爱成就每一位学生"); } }
package com.itheima_10; /* 测试类 */ public class PersonDemo { public static void main(String[] args){ //1、创建一个老师类对象 //无参构造 Teacher t1 = new Teacher(); t1.setName("张三"); t1.setAge(30); System.out.println(t1.getName() + "," + t1.getAge()); t1.teach(); //有参构造 Teacher t2 = new Teacher("李四", 33); System.out.println(t2.getName() + "," + t2.getAge()); t2.teach(); //2、创建一个学生类对象 //无参构造 Student s1 = new Student(); s1.setName("小明"); s1.setAge(18); System.out.println(s1.getName() + "," + s1.getAge()); s1.study(); //有参构造 Student s2 = new Student("小红", 19); System.out.println(s2.getName() + "," + s2.getAge()); s1.study(); } }
2、猫和狗:
package com.itheima_11; /* 动物类 */ public class Animal { //成员变量 private String name; private int age; //构造方法 public Animal(){}; public Animal(String name, int age){ this.name = name; this.age = age; } //set/get/show方法 public void setName(String name){ this.name = name; } public String getName(){ return this.name; } public void setAge(int age){ this.age = age; } public int getAge(){ return this.age; } public void show(){ System.out.println(getName() + "," + getAge()); } }
package com.itheima_11; /* 猫类 */ public class Cat extends Animal{ //构造函数 public Cat() { } public Cat(String name, int age) { //这里不能使用 this // 应为本类中没有提供这两个属性 而且父类中这两个属性是private没有继承过来 super(name, age); } public void catchMouse(){ System.out.println("猫抓老鼠"); } }
package com.itheima_11; /* 狗类 */ public class Dog extends Animal{ //构造方法 public Dog() { } public Dog(String name, int age) { //这里不能使用 this // 应为本类中没有提供这两个属性 而且父类中这两个属性是private没有继承过来 super(name, age); } public void lookDoor(){ System.out.println("狗看门"); } }
package com.itheima_11; /* 测试类 */ public class AnimalDemo { public static void main(String[] args){ //创建猫类对象并进行测试 Cat c1 = new Cat(); c1.setName("加菲猫"); c1.setAge(5); System.out.println(c1.getName() + "," + c1.getAge()); c1.catchMouse(); Cat c2 = new Cat("汤姆猫", 7); System.out.println(c2.getName() + "," + c2.getAge()); c2.catchMouse(); //创建狗类对象并进行测试 Dog d1 = new Dog(); d1.setName("旺财"); d1.setAge(5); System.out.println(d1.getName() + "," + d1.getAge()); d1.lookDoor(); Dog d2 = new Dog("来福", 8); System.out.println(d2.getName() + "," + d2.getAge()); d2.lookDoor(); } }
本文作者:如此而已~~~
本文链接:https://www.cnblogs.com/fragmentary/p/16749421.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步