继承是面向对象编程中的一个基本概念,它可以让一个类(子类或派生类)自动获取另一个类(父类或基类)的字段和方法。子类可以重写或扩展父类的方法和字段,以实现更具体或更特殊的行为。
继承的主要特性有以下几点:
代码复用:通过继承,子类继承了父类的所有属性和方法,使得在子类中可以直接使用父类的代码,避免了代码的重复编写,提高了代码的复用性。
封装性:父类的内部实现对子类是隐藏的,子类只能通过父类提供的接口进行访问,这就是封装性。封装性可以保护数据的完整性和安全性。
多态性:当子类继承了父类的方法后,可以对这些方法进行重写,使得父类引用指向子类对象时,会调用子类的方法,这就实现了多态性。
层次性:继承体现了一种层次关系,对类的功能进行分层次的描述,有助于我们更好地理解和设计程序。
可扩展性:当我们需要在现有类的基础上增加新的功能或者行为时,我们可以通过继承来实现,这就提高了代码的可扩展性
package com.exmaple.ObjectOriented.days20240110;
public class Extends{
public static void main(String[] args) {
Father f = new Father();
//子类型的引用得到的是,子类的字段name值
System.out.println(f.name); //1
Person p = new Father();
//父类的引用得到的是父类字段name的值
System.out.println(p.name); //人
}
}
class Person{
protected String name = "人";
}
class Father extends Person{
// protected int name = 18;
protected String name = "1";
}
如果子类定义父类同名的字段,会出现上面搞笑的一幕,不符合多态的特性
注意:这里的方法定义指:方法的修饰符,返回值类型,方法名和参数列表。
其中方法的修饰符:public > protected > default > private, 重写的方法修饰符只能大于等于父类方法修饰符,否则编译错误。
如果方法名一致,参数列表不一致,不会编译错误,这时叫方法的重载
package com.exmaple.ObjectOriented.days20240110;
public class Extends{
public static void main(String[] args) {
}
}
class Person{
protected String name = "人";
}
class Father extends Person{
public Father(){
//实际上是有super()存在,但是可以省略不写
// super();
}
public Father(String sex){
//实际上是有super()存在,但是可以省略不写
// super();
}
}
如果父类只写有参构造,编译器就不会自动给类添加无参构造,此时代码会编译错误
package com.exmaple.ObjectOriented.days20240110;
public class Extends{
public static void main(String[] args) {
}
}
class Person{
public Person(String name){
this.name = name;
}
protected String name = "人";
}
class Father extends Person{
//编译错误
public Father(){
//手动添加父类的有参构造就不会编译错误
// super("小明")
}
public Father(String sex){
//手动添加父类的有参构造就不会编译错误
// super("小明")
}
}
在大多数面向对象的编程语言中,一个类只能直接继承一个父类,这称为单继承。如Java、C#、Swift等语言都只支持单继承。
这样做的主要原因是多继承(一个类直接继承多个父类)可能会引发一些问题,比如菱形问题(也叫钻石问题)。菱形问题是指当一个类同时继承了两个具有相同方法的父类,那么在调用这个方法时,编译器就无法确定应该调用哪个父类的方法,这就引发了冲突。
尽管如此,有些语言(如C++和Python)支持多继承,但它们通过特殊的规则来解决上述问题,如C++中的虚继承,Python中的MRO(Method Resolution Order)。
另外,虽然一些语言只支持单继承,但是它们通过接口(如Java中的接口,C#中的接口)或者协议(如Swift中的协议)来实现类似多继承的效果。接口和协议可以被一个类多次实现,从而使得一个类可以拥有多个父类的特性