2022/07/28周四
Java 有三大特性: 封装 继承 多态
今天来学习一下继承
一、从生活的角度看继承我们无时无刻不在继承着父辈们(甚至更向上)给予我们的一切
包括 基因血缘、相貌特征、行为方式、当然还有生活的必需品 money
但是也有我们不能够去继承的,那些私有的(private)。(这个问题不用向深处考虑,很浅显易懂)
生活映射具体事物,java源于生活,面向事物特征,正如道教 1生2,2生3,3生万物般,
对于整个世界(Object)来说,我们都是子类(Subclass)...
二、Java中的继承基本概念:
继承是类与类之间的关系,继承的基本思想是,基于已有的类创造新的类。
继承已存在的类就是复用这些类的方法,而且可以增加一些新的方法和字段,使新类能够适应新的情况。
继承是Java程序设计中一项核心技术,它主要解决的问题是:共性的抽取,实现代码复用。
语法格式:
修饰符 class B(子类) extends A(父类) {
}// B类 继承了 A类
// B 是 A 的子类,A 是 B 的父类
入门案例:
//创建动物类
class Animals{
//封装私有属性
private String name;
private String kind;
private int age;
//无参构造
public Animals() {
System.out.println("I have some dogs -->");
super();
}
//有参构造
public Animals(String name, String kind, int age) {
super();
this.name = name;
this.kind = kind;
this.age = age;
}
// set 和 get 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//创建成员方法
//展示动物信息 showMesge()
public void showMesge() {
System.out.println("名字:"+this.getName() + " 品种:" + this.getKind() + " 年龄:" + this.getAge() + " 岁");
}
//创建私有化方法
private void shouMesgeName() {
System.out.println("私有名字:"+ this.name);
}
}
//创建 Dog 类继承 Animals类 使用extends关键字
class Dog extends Animals{
public Dog() {
super();
}
public Dog(String name, String kind, int age) {
//super关键字调用父类构造方法
super(name, kind, age);
}
}
public class Test{
public static void main(String[] args) {
//实例化狗类对象 dog1 用set方法赋值
Dog dog1 = new Dog();
dog1.setName("哈奇");
dog1.setKind("哈士奇");
//调用父类方法showMesge()
dog1.setAge(3);
dog1.showMesge();
//实例化狗类对象 dog2 用构造方法进行赋值
Dog dog2 = new Dog("阿花", "中华田园犬", 4);
//调用父类方法showMesge()
dog2.showMesge();
//实例化狗类对象 dog3
Dog dog3 = new Dog();
//父类私有化的成员属性不能直接调用 (若没有set方法,就完全不能使用)
//dog3.name = "阿柴";
//父类私有化的成员方法 不能使用
dog3.showMesgeName();
}
}
如上面案例所示:
三、关于父类子类的内存分析1.父类私有的成员属性和方法子类不能使用
2.子类并不继承父类的构造方法,但是可以调用父类的构造方法,例如使用super(参数,...)
3.在实例化一个子类对象后,会先执行父类的构造方法,再执行子类的构造方法
详解:子类中所有的构造函数都会默认访问父类中的空参数构造函数,这是因为子类的构造函数内第一行都有默认的super()语句。
super()表示子类在初始化时调用父类的空参数的构造函数来完成初始化。
所以在本例中,在实例化一个子类对象时,会打印输出 "I have some dogs -->"
4.若父类中只存在有参构造(此时默认的无参构造消失),没有无参构造时,子类会报错,此时要加super(参数,...),如上面代码中 Dog子类的有参构造 super(name, kind, age); 所示
详解:一个类都会有默认的空参数的构造函数,若指定了带参构造函数,那么默认的空参数的构造函数,就不存在了。这时如果子类的构造函数有默认的super()语句,那么就会出现错误,因为父类中没有空参数的构造函数。因此,在子类中默认super()语句,在父类中无对应的构造函数,必须在子类的构造函数中通过this或super(参数)指定要访问的父类中的构造函数。
5.父类与子类的构造方法的形式要保持一致
6.父类中有无参构造,子类也要有无参构造,父类无 无参构造,则子类也无 无参构造
四、重写
重写目的:
当父类的非私有方法不满足子类需求时,就需要重写父类的非私有方法
重写特征:
参数列表与被重写方法的参数列表必须完全相同。
返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类
访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
父类的成员方法只能被它的子类重写。
声明为 final 的方法不能被重写。
声明为 static 的方法不能被重写,但是能够被再次声明。
子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
构造方法不能被重写。
重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
如果不能继承一个类,则不能重写该类的方法。
重写基本要求:(与特征相似,再次强调)
1.必须要有继承关系
2.父类的方法必须是非私有化的
3.要在子类中重写父类的方法,这个方法除了方法体不一样外,其他都一样
4.必须在子类中去重写父类的非私有化方法
重写格式:
@Override
父类非私有化方法
重写案例:
class Animal{
//父类方法
public void eat() {
}
public void sport() {
}
}
class Panda extends Animal{
@Override
public void eat() {
System.out.println("熊猫喜欢吃竹子");
}
@Override
public void sport() {
System.out.println("熊猫不爱运动,喜欢睡觉");
}
}
public class Demo02 {
public static void main(String[] args) {
Panda panda = new Panda();
panda.eat();
panda.sport();
}
}
五、重写(Override)与重载(Overload)的区别
方法重载:
- 被重载的方法必须改变参数列表(参数个数或类型不一样);
- 被重载的方法可以改变返回类型;
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
- 无参构造和有参构造 也是一种重载
- 方法的重载必须在同一个类中
含义不同:
1.方法重载是在同一个类中,声明多个同名方法,通过参数列表来区分不同的方法,与参数列表的数量、类型和顺序有关,与修饰符和返回值类型以及抛出异常类型无关
2.方法重写(方法覆盖)的前提是发生在具有继承关系的两个类之间,方法重写有以下规则:参数列表,返回值,方法名必须保持一致
重写方法的访问权限范围必须大于等于父类方法
重写方法的抛出异常类型范围不能大于父类方法
作用不同:
重载:在同一个类中为一种行为提供多种实现方式并提高可读性
重写:父类方法无法满足子类的要求,子类通过方法重写满足需求
有关于继承的相关概念就简单介绍到这里。。。



