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();
}
}
标签:Java,继承,子类,age,System,println,父类,public
From: https://www.cnblogs.com/fragmentary/p/16749421.html