Mekanisme pewarisan: pengaturcaraan berorientasikan objek ialah. Cara penggunaan semula kod yang paling penting membolehkan pengaturcara memanjangkan dan menambah fungsi baharu sambil mengekalkan ciri kelas asal Kelas baharu yang dihasilkan menjadi kelas/subkelas terbitan. Masalah utama yang diselesaikan oleh warisan ialah: pengekstrakan ciri biasa dan realisasi penggunaan semula kod.
menunjukkan hubungan warisan antara kelas Anda perlu menggunakan kata kunci extends adalah seperti berikut:
Subkelas/kelas terbitan kelas pengubah memanjangkan kelas induk/kelas asas/kelas super {
//…………
}
Subkelas akan mewarisi pembolehubah ahli atau kaedah ahli kelas induk ke dalam subkelas
Selepas subkelas mewarisi kelas induk, ia mesti menambah kelasnya sendiri ahli unik , mencerminkan perbezaan daripada kelas asas
Apabila tiada pembolehubah ahli dengan nama yang sama, akses biasa sudah memadai
Jika terdapat pembolehubah ahli dengan nama yang sama, gunakan (super .nama pembolehubah) untuk mengakses pembolehubah ahli kelas induk
Apabila mengakses pembolehubah ahli, akses pembolehubah ahli anda sendiri dahulu. Iaitu, apabila mengakses pembolehubah ahli dengan nama yang sama, akses kepada subkelas diberi keutamaan. Iaitu: subkelas menyembunyikan ahli kelas induk
Akses pembolehubah ahli mengikut prinsip kedekatan Jika anda mempunyai satu, anda mempunyai keutamaan. anda akan mencarinya dalam kelas induk.
Kaedah ahli dengan nama berbeza boleh diakses secara normal
Kaedah ahli mempunyai nama yang sama dan anda boleh mengakses kaedah kelas induk dengan nama yang sama melalui [nama super.method]
Jika parameter senarai kelas induk dan kaedah subkelas dengan nama yang sama adalah berbeza ( Overloading), pilih kaedah yang sesuai untuk diakses berdasarkan parameter yang diluluskan semasa memanggil kaedah.
Jika prototaip kaedah dengan nama kelas induk dan subkelas yang sama adalah konsisten, akses subkelas
Fungsi utama kata kunci super ialah: Akses ahli kelas induk dengan nama yang sama dalam kaedah kelas. (Hanya boleh digunakan dalam kaedah bukan statik)
public class Base { int a; int b; int c; } public class Derived extends Base{ int a; // 与父类中成员a同名,且类型相同 char b; // 与父类中成员b同名,但类型不同 public void method(){ a = 100; // 访问父类继承的a,还是子类自己新增的a? b = 101; // 访问父类继承的b,还是子类自己新增的b? c = 102; // 子类没有c,访问的肯定是从父类继承下来的c } }
Apabila membina objek subkelas, anda perlu memanggil kaedah pembinaan kelas induk dahulu, dan kemudian. laksanakan pembinaan kaedah subkelas.
public class Base { int a; int b; public void methodA(){ System.out.println("Base中的methodA()"); } public void methodB(){ System.out.println("Base中的methodB()"); } public class Derived extends Base{ int a; char b; // 与父类中methodA()构成重载 public void methodA(int a) { System.out.println("Derived中的method()方法"); } // 与父类中methodB()构成重写 public void methodB(){ System.out.println("Derived中的methodB()方法"); } public void methodC(){ a = 100; // 等价于: this.a = 100; b = 101; // 等价于: this.b = 101; // 访问父类的成员变量时,需要借助super关键字 // super是获取到子类对象中从基类继承下来的部分 super.a = 200; super.b = 201; methodA(); // 没有传参,访问父类中的methodA() methodA(20); // 传递int参数,访问子类中的methodA(int) methodB(); // 直接访问,则永远访问到的都是子类中的methodA(),基类的无法访问到 super.methodB(); // 访问基类的methodB() } }
Jika kelas induk mentakrifkan pembina tanpa parameter atau lalai secara eksplisit, akan ada panggilan super() tersirat secara lalai dalam baris pertama pembina subkelas.
Apabila kelas induk mentakrifkan pembina dengan parameter, pengkompil tidak lagi akan menjana pembina lalai untuk subkelas tersebut perlu ditakrifkan secara eksplisit dan disertakan dalam pembina subkelas pembina kelas induk yang sesuai
Dalam pembina subkelas, super(……) memanggil pembina kelas induk dan mestilah pernyataan pertama bagi pembina subkelas
super(……) hanya boleh muncul sekali dalam pembina subkelas, dan tidak boleh muncul pada masa yang sama dengan ini
【注】Java中不支持多继承
super只能指代直接父类
继承关系一般不超过三层
修饰变量时,表示常量(不能修改)
修饰类:此类不能被继承
修饰方法:表示方法不能被重写
组合和继承都能实现代码的复用。组合没有涉及到特殊的语法(如extend关键字),仅仅是将一个类的实例作为另一个类的属性。
继承表示对象与对象之间是is-a的关系
组合表示对象与对象之间是has-a的关系
一般建议:能用组合尽量用组合
通过父类类型的引用调用子类对象,向上转型是安全的
【发生向上转型的时机】
直接赋值
方法传参
函数的返回值
public class TestAnimal { // 2. 函数传参:形参为父类引用,可以接收任意子类的对象 public static void eatFood(Animal a) { a.eat(); } // 3. 作返回值:返回任意子类对象 public static Animal buyAnimal(String var) { if ("狗" == var) { return new Dog("狗狗", 1); } else if ("猫" == var) { return new Cat("猫猫", 1); } else { return null; } } public static void main(String[] args) { Animal cat = new Cat("元宝", 2); // 1. 直接赋值:子类对象赋值给父类对象 Dog dog = new Dog("小七", 1); } }
优缺点:
优点:让代码更加灵活
缺点:不能访问到子类特有的方法
函数名相同、参数列表相同、返回值相同或是【协变类型】(父子类关系)
【方法重写的规则】
重写的方法访问权限不能比父类中原方法的的权限低;
父类中被static、private、final修饰的方法、构造方法不能被重写;
重写的方法,可以使用 @override 注解来显示指定(帮助我们进行一些合法性的检验)。比如方法名拼写错误,编译会报错;
重写的返回值类型可以不同,但是必须具有父子关系。
被final修饰的方法,叫做密封方法,该方法不能被重写。
外部类只能是public或者默认权限
【动态绑定和静态绑定】
动态绑定:发生的条件(1、父类引用引用子类对象;2、通过父类引用,可以访问到子类中的方法)。后期绑定,即在编译时不能确定方法的行为,需要等到程序运行时,才能够确定调用哪个类的方法;
静态绑定:前期绑定,编译时,根据用户传递的参数类型确定具体的调用方法(函数重载)
一个引用调用同一个方法,可以表现出不同的形式,这种思想称为多态。在父类的构造方法中不要调用重写的方法。
【多态实现的条件】
必须在继承条件下
子类对父类方法进行重写
通过父类引用调用重写的方法
发生了向上转型
public class Animal(){ String name; int age; public Animal(String name, int age){ this.name = name; this.age = age; } public void eat(){ System.out.println(name + "吃饭"); } } public class Cat extends Animal{ public Cat(String name, int age){ super(name, age); } @Override public void eat(){ System.out.println(name+"吃鱼~~~"); } } public class Dog extends Animal { public Dog(String name, int age){ super(name, age); } @Override public void eat(){ System.out.println(name+"吃骨头~~~"); } } public class TestAnimal { // 编译器在编译代码时,并不知道要调用Dog 还是 Cat 中eat的方法 // 等程序运行起来后,形参a引用的具体对象确定后,才知道调用那个方法 // 注意:此处的形参类型必须时父类类型才可以 public static void eat(Animal a){ a.eat(); } public static void main(String[] args) { Animal animal1 = new Cat("元宝",2); Animal animal2 = new Dog("小七", 1); eat(animal1); eat(animal2); } }
【注】Java中所有的类默认继承Object类
Atas ialah kandungan terperinci Pengenalan kepada konsep dan kaedah pelaksanaan warisan dan polimorfisme Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!