咱不讲继承在教科书上石板的定义,简单举个例子,我们在养猫和狗时,我们都会给他们名字,他们都有年龄,都会吃饭,睡觉。我们把这些共同点归类起来写一个类,这个类就是父类,不同点在分开写2个类,即子类。
我们定义一个父类
public class Same {
public String name;
public int age;
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
定义子类时要使用关键字extends。方式:修饰符 class 子类 extends 父类
public class dog extends Same {
public void bark(){
System.out.println("旺旺");
}
}
public class cat extends Same{
public void mew(){
System.out.println("喵喵喵");
}
}
1. 子类会将父类中的成员变量或者成员方法继承到子类中了
2. 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
父类成员的访问 1.在子类方法中 或者 通过子类对象访问成员时 : 如果访问的成员变量子类中有,优先访问自己的成员变量。 如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。 如果访问的成员变量与父类中成员变量同名,则优先访问自己的。 成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找 2.通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。 通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同 ( 重载 ) ,根据调用方法适传递的参数选择合适的方法访问,如果没有则报错; super关键字 如果要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的,Java 提供了 super 关键字,该关键字主要作用:在子类方法中访问父 类的成员public class Base {
public int a;
public char b;
public void methodA(){
System.out.println("这是Base中的方法A");
}
}
public class Derived extends Base {
public int a;
public int b;
@Override
public void methodA() {//重写
super.methodA();
}
public void methodA(int a){//重载
System.out.println("这是子类中的methodA");
}
public void methodB(){
//this是当前对象的引用,对于同名的成员变量,直接访问时,访问的都是子类的
this.a=10;
this.b=20;
//访问父类成员变量,使用super关键字,super是获取到子类对象中从基类继承下来的部分
super.a=100;
super.b=30;
//对于重载函数,只要分清参数即可
methodA();
methodA(10);
//要访问重写函数的基类方法,要使用super
super.methodA();
}
}
子类的构造方法
对于子类来说,是先继承。所以再写构造方法时第一句是super();否则会报错。
在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执 行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子 肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整 ,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。 注意: 1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的 super() 调用,即调用基类构造方法 2. 如果父类构造方法是带有参数的,此时编译器不会再给子类生成默认的构造方法,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。 3. 在子类构造方法中, super(...) 调用父类构造时,必须是子类构造函数中第一条语句。 4. super(...) 只能在子类构造方法中出现一次,并且不能和 this 同时出现 继承关系上的执行顺序
public class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person的构造方法");
}
{
System.out.println("person的实例代码块");
}
static {
System.out.println("person的静态代码块");
}
}
public class Student extends Person{
public Student(String name, int age) {
super(name, age);
System.out.println("这是Student的构造方法");
}
{
System.out.println("这是Student的实例代码块");
}
static {
System.out.println("这是Student的静态代码块");
}
}
public class Test {
public static void main(String[] args) {
Student student1=new Student("yao",20);
System.out.println("=========================");
Student student2=new Student("li",21);
}
}
1 、父类静态代码块优先于子类静态代码块执行,且是最早执行 2 、父类实例代码块和父类构造方法紧接着执行 3 、子类的实例代码块和子类构造方法紧接着再执行 4 、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行 protect关键字 继承方式
继承关系一般不超过3层
final关键字final a=10; a=20//编译失败
final public class Base{
............
}
public class Derived extends Base{
............
}//final修饰的类无法被继承
继承和组合
继承表示对象之间是
is-a
的关系
,比如:狗是动物,猫是动物
组合表示对象之间是
has-a
的关系,比如:汽车
// 轮胎类
class Tire{
// ...
}
// 发动机类
class Engine{
// ...
}
// 车载系统类
class VehicleSystem{
// ...
}
class Car{
private Tire tire; // 可以复用轮胎中的属性和方法
private Engine engine; // 可以复用发动机中的属性和方法
private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
}//组合
// 奔驰是汽车
class Benz extend Car{
// 将汽车中包含的:轮胎、发送机、车载系统全部继承下来
}
一般建议:能用组合尽量用组合。


