面向对象基础9(继承)
封装、继承、多态是面向对象的三大特征
继承的理解
苹果(类)继承了水果(类)
老虎(类)继承了动物(类)
- Java的继承是类与类之间的关系
- 是一种由一般到特殊的关系(与现实中的辈分没有关系,所以子类和父类名字并不准确)
——小类(子类)是一种特殊的父类(大类)
子类的实例完全可当做父类的实例来使用
别称
父类(超类、基类、大类);子类(派生类、小类)
继承的语法
修饰符 class 类名 extends 父类
{代码块}
说明:
Java是单继承的,所以,一个子类只能继承一个父类
若不显示继承父类,Java会默认继承Object类
——一切皆Object!
举例:
public class A {}class B extends A{}class C extends B{}//C的直接父类是B;Object、A是C的间接父类(我附庸的附庸不是我的附庸...)//A的直接子类是B,间接子类是C
继承的作用:
子类继承父类,就可以直接使用父类的方法和成员变量
举例1:
public class Bird {public void fly(){System.out.println("Birds Flying");}}class Sparrow extends Bird{}//此处Sparrow类继承Bird类,Sparrow类并没有写任何方法但继承了Bird类的方法
public class SparrowTest {public static void main(String[] args) {Sparrow sp=new Sparrow();sp.fly();}}/*Birds Flying*/
继承的优点是可以实现代码的复用
方法重写
存在意义
当子类发现父类的方法不适合自己的时候,就需要重写方法
规则
两同两小一大:
两同:方法名相同、形参列表相同;
两小:返回值类型相同或者更小,声明抛出的异常相同或者更小;
一大:访问权限相同或者更大
举例2:
public class Ostrich extends Bird{//重写fly方法@Overridepublic void fly(){System.out.println("can not fly");}}
public class OstrichTest {public static void main(String[] args) {Ostrich A=new Ostrich();A.fly();}}/*can not fly*/
此时原有的fly方法被重写
注解@Override——用于报错,要求被修饰的方法必须重写父类方法,否则就报错(方法拼写错误);
Super关键字
与this引用很相像,super可以用于限定访问父类的实例变量和实例方法。
super.父类的实例变量
super.父类的实例方法(参数)
例3:
class Base {int age=2;}class Sub extends Base{int age =20;public void test(){int age=200;System.out.println(age);System.out.println(this.age);//调用该类中的成员变量System.out.println(super.age);//调用父类中的成员变量public void names(String name){System.out.println("执行父类"+name);}}}public class SubTest {public static void main(String[] args) {Sub A=new Sub();A.test();}}/*200202*/
例3改:
class Base {int age=2;}class Sub extends Base{public void test(){System.out.println(age);System.out.println(this.age);System.out.println(super.age);}//此处删除了原有的局部变量与子类中的成员变量}public class SubTest {public static void main(String[] args) {Sub A=new Sub();A.test();}}/*222*/
从上面两个例子可以看出:
变量的调用遵循就近原则,输出的age变量优先调用所属方法的局部变量,若局部变量不存在,其次考虑所属类的实例变量(此处是子类),最后考虑其父类的实例变量。
而this和super关键字再次就是为了打破就近原则,调用所需要的变量。
class Base {public void names(String name){System.out.println("执行父类"+name);}}class Sub extends Base{public void names(String name){System.out.println("执行子类"+name);}public void test(){names("Java");/*此处等同于this.names("Java");等同于Base.names("Java");类方法需要类来调用,默认添加类名*/super.names("Java");}}public class SubTest {public static void main(String[] args) {Sub A=new Sub();A.test();}}/*执行子类Java执行父类Java*/
此时带有super关键子的names方法会打破就近原则,执行父类的原有方法。
子类调用父类的构造器
子类的构造器一定要调用父类的构造器一次(有且仅有一次)
- 如果子类构造器没有显示调用父类构造器,系统会在子类构造器的第一行自动调用父类无参数的构造器;
- 子类构造器的第一行显示使用
super调用父类构造器:super()
super和this关键字不顾能出现在同一语句
例5:
package Super关键字;class Fruit{private double weight;public Fruit(double weight){this.weight=weight;}}public class Apple extends Fruit {public Apple() {super(2.2);//常识调用父类Fruit的double构造器}}
备注:如果父类没有无参构造器——则子类构造器必须显示调用(super调用,如上例)父类的构造器
