概述
继承指一个类(通常称为子类),去继承另一个类(通常称为父类)的属性和方法,通过继承子类可以使用父类的属性和方法.
继承主要解决的问题就是:共性抽取,抽取不同类之间的共性代码,减少代码冗余和编程时间.
继承是多态的前提,没有继承就没有多态.
使用
继承格式
public class 类名extends 继承的父类名(){}
案例
1.编写父类Father
public class Father {
String name="我是父类";
public void method(){
System.out .print1n("父类成员方法");
}
2.编写子类Son,并继承父类
public class Son extends Father{}
3.通过子类对象调用父类属性及方法
public class Main {
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.name);
son .method();
}
方法 重写/覆盖(Override)
规则
1.必须保证父子类方法名相同,参数列表也相同
2.子类方法的返回值类型必须小于等于父类返回值类型的范围
3.可以通过 @Override 注解判断是否覆盖重写
4.子类方法的权限必须 大于等于 父类的权限修饰符
public > protected > defalut(啥都不写) > private
属性或方法重名
子类与父类的属性或方法重名.
1.直接使用 对象名.属性名.
实例化时等号左边是谁,就优先用谁,没有就向上找.
案例
1)为子类添加同样的成员属性name和成员方法method.
public class Son extends Father{
String name="我是子类";
public void method(){
System.out.print1n("子类成员方法");
}
2)调用子类对象的name属性和method方法
public class Main {
public static void main(String[] args) {
Son son = new Son();
System.out.println( son. name);
son.method();
}
2.间接使用->通过成员方法访问成员变量
该方法属于谁就访问谁的成员变量,没有则向上找
案例
1)给父类添加fatherMethod方法
public class Father {
String name="我是父类";
public void method(){
System.out.print1n("父类成员方法");
}
public void fatherMethod( ){
System.out.print1n(name);
}
}
2)通过子类对象调用该方法,得到的name为父类中的
public class Main {
public static void main(String[] args) {
Son son = new Son();
son.fatherMethod() ;|
}
}
在子类中,父类成员变量、子类成员变量、局部变量重名,如何区分?
局部变量:直接写
子类成员变量:this.成员变量名/成员方法名
父类成员变量: super.父类成员变量名/父类方法名
案例
1.为子类添加show方法
public class Son extends Father{
String name="我是子类";
public void method(){
System.out.println("子类成员方法");
}
public void show(String name){
System.out.println(name);
System.out.println("this.name:"+this.name);
System.out.println("super.name:"+super.name);
}
}
2.调用show方法展示结果
public class Main {
public static void main(String[] args) {
Son son = new Son();
son.show("我是传入的参数");
}
}
this()指代本类中的构造方法,super()指父类中的构造方法。两者在某一类中只能出现一次,且必须在构造方法中的第一行.
继承中父与子类的构造方法
1.父子构造均无参数
在调用子类实例化时,会自动调用父类的构造方法。(默认先调用父类的构造方法,后调用自己的构造方法)
案例
1)父类无参构造函数
public class Father {
public Father(){
System.out.println("父类无参构造函数");
}
}
2)子类无参构造函数
public class Son extends Father{
public Son(){
System.out.println("子类无参构造函数");
}
}
3)实例化子类对象,查看结果
public class Main {
2.父类有参数
子类在继承时会报错
解决方案
1)需要继承无参构造方法,父类中进行方法重载,编写一个无参构造方法
public class Father {
public Father(){}
public Father(String str){
System.out.print1n("父类无参构造函数");
}
}
2)需要继承有参构造方法,在子类中直接调用 super(父类构造函数参数列表);
(注意事项:必须在子类构造方法中的调用,只能调用一次)
public class Son extends Father{
public Son(){
super( str: "一个参数");
System.out.print1n("子类无参构造函数");
}
继承的特性
1.子类拥有父类非 private 的属性、方法。
2.子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
3.子类可以用自己的方式实现父类的方法。
4.Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
5.提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
抽象方法
概念:
假设现在有三角形类、圆形类、正方形类三个类,它们都继承了一个父类图形类,图形类中有一个计算面积的方法,显然这个方法并不能同时适用于3个子类,因为圆形面积是πr2 ,正方形面积为边长的平方。所以该方法要在子类中进行覆盖重写.
在父类中该方法不需要有方法体,只需要有个方法名,这种方法就称为抽象方法.Java中提供了专门的修饰符,来修饰抽象方法.
格式:
在方法类型前加上abstract修饰符,则表明该方法为抽象方法.
//抽象方法必须在抽象类中,在类前加abstract 修饰符即为抽象类
public abstract class Father {
//抽象方法
public abstract void method( );
}
如何使用抽象类和抽象方法
1.不能直接new(实例化)抽象类对象.
2.必须用一个子类继承该父类
3.必须在子类中重写覆盖所有抽象方法,去掉abstract,补上大括号
public class Son extends Father {
@Override
public void method() {
System.out.print1n("在子类中重写了抽象方法");
}
注意事项
1.不能用抽象类创建对象,如果创建,编译无法通过而报错。
理解:调用抽象类的抽象方法,没有具体的方法体,没有意义。
2.抽象类中,可以有构造方法,在子类创建对象时,会自动调用。
理解:子类实例化时原本就会调用父类构造方法,在抽象类中一样适用。
3.抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计,比如适配器模式。
4.抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
END
编 辑 | 王文星
责 编 | 木有符号