java-2 继承

什么是继承

继承是把两个类的共性抽取,放到一个类当中

class Dog{
    public int length;

    public void bark(){
        System.out.println(length+"www");
    }

}

class Cat{
    public int length;

    public void miao(){
        System.out.println("miao");
    }

}
public class L515 {
    public static void main(String[] args) {

    }
}

通过在创建一个类,另外一两个类extend这个类来实现

class Animal{
    public int length;

}

class Dog extends Animal{
//    public int length;
    public  int kemomimi;

    public void bark(){
        System.out.println(length+"www");
    }

}

class Cat extends Animal{
//    public int length;

    public void miao(){
        System.out.println(length+"miao");
    }

}
public class L515 {
    public static void main(String[] args) {

    }
}

现在不需要重定义length了,代码量缩减。此时的Dog叫做子类(派生类),Anim叫做父类(基类,超类)

继承过来后,会保持原有属性,扩展父类属性

public class L515 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.kemomimi=1;
        dog.length=2;
    }
}

子类访问父类的成员变量

当子类和父类不存在同名变量的时候

class Test{
    public int a = 1;
    public int b = 2;
}
class Homewark extends Test{
    public int c = 3;
    public int d = 4;

    public void print(){
        System.out.println(this.c);
        System.out.println(this.b);
        System.out.println(this.c);
        System.out.println(this.d);
    }

}
public class L515 {
    public static void main(String[] args) {
        Homewark homewark = new Homewark();
        homewark.print();
    }
}

 有同名状况的时候

class Test{
    public int c = 1;
    public int b = 2;
}
class Homewark extends Test{
    public int c = 3;
    public int d = 4;

    public void print(){
        System.out.println(this.c);
        System.out.println(this.b);
        System.out.println(this.c);
        System.out.println(this.d);
    }

}
//如果子类中有同名的,输出会优先访问子类自己的方法
//如果访问的成员变量子类没有,则会访问父类继承的,父类如果也没有则会报错

如果需要访问父类的c .成员变量改成super.c;

super是子类从父类继承的空间的地址

class Test{
    public int c = 1;
    public int b = 2;
}
class Homewark extends Test{
    public int c = 3;
    public int d = 4;

    public void print(){
        System.out.println(super.c);
        System.out.println(this.b);
        System.out.println(this.c);
        System.out.println(this.d);
    }

}

子类访问父类成员方法

class Test{
    public int c = 1;
    public int b = 2;

    public void resolve(){
        System.out.println("父类");
    }
}
class Homewark extends Test{
    public int c = 3;
    public int d = 4;

    public void print(){
        System.out.println(super.c);
        System.out.println(this.b);
        System.out.println(this.c);
        System.out.println(this.d);
    }

    public void method(){
        System.out.println("子类");
    }

}
public class L515 {
    public static void main(String[] args) {
        Homewark homewark = new Homewark();
        homewark.print();
        homewark.method();
        homewark.resolve();
    }
}

  有同名状况的时候

优先原理同成员变量的原理。需要在非静态方法里用super.父类方法名来进行访问

    public void method(){
        System.out.println("子类");
        super.method();
    }

只能在非静态方法中使用,static和super不能共存。

注意

当我们给父类按照一般的情况写上构造方法时,子类会保错

 子类对象构造完成之前,需要先对父类的成员初始化。

需要在子类新建的构造方法上加上父类构造方法的参数,内部进行super

    public Homewark(int c, int d){
        super(c,d);
    //super只能放在第一行,this也要放到第一行,因此this和super不能共存
    }

注意:

一个类的两个方法,无论是在同一个类中声明的,还是由一个类继承的,都是重载。

protect关键字

在默认的功能下加了不同包的子类下也可以使用。

在L520下新建一个类

class dog{
    protected int longth =1;
}
public class L520 {

}

然后在test下也写上子类并用super来调用。

class Animal extends dog{
    public void print(){
        System.out.println(super.longth);
    }
}

public class test {
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.print();

    }
}

 Java中的继承

1.单继承,一个类只能继承另外一个类,不能继承多个类。

class Dog extends Cat{
}
class Cat{
    
}
class Chicken{
    
}
public class L520 {

}

2.多重继承。

class Dog {
}
class Cat extends Dog{

}
class Chicken extends Cat{

}
public class L520 {

}
//在一个类前加上final的时候,这个类就不会被继承了。

此时狗是猫的父类,猫是鸡的父类,就是多重继承,多重继承最底下的会保留上层的成员变量和成员方法。

3.不同类继承同一类。

class Dog {
}
class Cat extends Dog{

}
class Chicken extends Dog{

}
public class L520 {

}

4.一个类不能继承两个类。

但是3中,一直继承下去一个类过于冗杂,因此我们有了接口。

继承和组合

组合是表达类之间关系的方式,也能达到代码重用的效果。,仅仅是将一个类的实例作为另外一个类的字段

class  Teacher{

}
class Student{

}
class School{
    private Student[] students;
    private Teacher[] teachers;
}
public class L520 {
    public static void main(String[] args) {

    }
}

学生和老师两个类中的成员变量成员方法等,学校类中都可以拿到。相对于继承,我们优先考虑组合。

多态

加上多种形态,具体点加上去完成某种行为,不同对象去完成时会有不同的状态。

要实现多态,需要满足两个要求,一个是向上转型,另一个是重写。

向上转型

先写一个普通代码:
 

class  Teacher{
    private String name;
    //后面加上构造方法,getterandsetter和tostring

    public Teacher(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name=" + name +
                '}';
    }

    public void teach(){
        System.out.println("正在上课");
    }
}

class Student extends Teacher{
    //初始化父类对象
    public Student(String name) {
        super(name);
    }

    public void shout(){
        System.out.println(getName()+"为什么不下课");
    }

}

class School extends Teacher{

    public School(String name) {
        super(name);
    }

    public void over(){
        System.out.println(getName()+"应该下课啦");
    }
}

public class L520 {
    public static void main(String[] args) {
        Student student = new Student("王鸿");
        student.shout();
    }
}

向上转型就是把student赋给teacher;

public class L520 {
    public static void main(String[] args) {
        Student student = new Student("王鸿");
        Teacher teacher =student;
//或者写成:
//      Teacher teacher = new Student("王鸿");
    }
}
//也就是把子类给父类了。

向上转型可以成功因为student是teacher的子类。

此时只能调用teacher自己内部的东西,不能调用子类的东西。

还有一种向上转型的方式:方法的传参

public class L520 {
    public static void func(Teacher teacher){

    }
    public static void main(String[] args) {
       Student student = new Student("王鸿");

       func(student);
    }
}

在student是teacher子类的情况下,通过主类的函数去直接传入父类的形参,然后在主函数中调用参数为子类的方法。

这个时候只需要new子类的对象。

还有一种:方法的返回值

    public static Teacher func(){
        return new Student("画画");
    }
    public static void main(String[] args) {
       Student student = new Student("王鸿");

       func(student);
    }

在返回值上,同样可以发生向上转型

向下转型(不经常使用,因为不安全)

    public static void main(String[] args) {
//       Student student = new Student("王鸿");
//       Teacher teacher = student;
        Teacher teacher =new Teacher("王鸿");
        Student student = (Student) teacher;

    }

但是当我们运行时会报错,需要:

    public static void main(String[] args) {
//       Student student = new Student("王鸿");
//       Teacher teacher = student;
        Teacher teacher =new Teacher("王鸿");
        if(teacher instanceof Student) {
            Student student = (Student) teacher;
            student.shout();
        }

    }

if是为了判断这个引用是不是这个类型的实例

重写(复写)(覆盖)

重写要求:

方法名相同,

方法的参数列表相同(个数,类型,顺序)

方法的返回值相同,(方法返回值可以不相同,比如子类的返回值和父类的返回值是父子类关系,也叫协变类型,也可以构成重载)

static的方法不能被重写,

private的方法不能被重写,

子类修饰的访问修饰符的权限,需要大于等于父类的访问修饰符的权限。

不想重写方法的话加上final就可以避免被重写,术语叫做密封方法。

以上就可以实现多态了,多态的基础上加上通过父类的引用,调用这个重写的方法就可以构成动态绑定。

动态绑定(运行时绑定)

在编译的时候,父类的方法还会是自己的,在运行的时候,程序发生了动态绑定,调到了子类自己的。

而静态绑定呢,则是在编译的时候,根据用户所传递的实参类型就确定了调用的具体方法,例如函数的重载,因此也称前期绑定。

class  Teacher{
    private String name;

    public Teacher(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name=" + name +
                '}';
    }
    
    //此时teacher这个父类中有teach和shout两个方法。
    public void teach(){
        System.out.println("正在上课");
    }
    public void shout(){
    }

}
class Student extends Teacher{
    public Student(String name) {
        super(name);
    }

    //但是子类也有两个同名的方法。
    public void shout(){
        System.out.println(getName()+"为什么不下课");
    }
    public void teach(){
        System.out.println("正在上课啊");
    }

}

向上转型后,父类一般是调用不了子类方法的,但是当父类和子类发生了多态的时候,子类父类都有同名的方法,此时使用父类名就可以引用子类的具体方法,而与父类另一同名方法的具体实现无关。

动态绑定是多态的一个基础。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值