目次
- 1. 動的バインディング機構
- 2. 多態性配列
- 3. 多態性配列の高度な使用法
- 4. 多態性パラメータ
- 5. 多態性パラメータの高度な使用法
1. 動的バインディング機構
Java の動的バインディング メカニズムは非常に重要です
例A
例を見てみましょう:
![](https://img-blog.csdnimg.cn/img_convert/8cd5e783a15b257abb46b9c760108ef2.jpeg)
上記のコードを読んで、次のプログラムが何を出力するかを説明してください。
![](https://img-blog.csdnimg.cn/img_convert/3210f8abf2d5434488a8844674eb0997.png)
プログラムは 40 と 30 を出力します。この例は非常に単純です。実行中の型に注目してください。コードの実行中の型は B なので、クラス B のメソッドが呼び出されます。
例B
上記のコードを変更して、サブクラス内の次のコード ブロックをログアウトしてみましょう。
![](https://img-blog.csdnimg.cn/img_convert/53bb2b6442a0e789e040ea79c656c7c2.png)
次に、継承メカニズムは親クラスの sum メソッドにアクセスします。
![](https://img-blog.csdnimg.cn/img_convert/5b22e9edb5f214565d717b45a6730501.png)
ここで質問がありますが、ここでの getI() はサブクラスを実行しますか、それとも親クラスを実行しますか?
オブジェクトメソッドを呼び出すと、メソッドはオブジェクトのメモリアドレス/実行タイプにバインドされます。
コードの実行型は依然として B であるため、サブクラスの getI() メソッドがここで実行され、結果出力は 30 になります。
例C
上記のコードを次のように変更してみましょう
次に、サブクラス内の次のコード ブロックをキャンセルします。
![](https://img-blog.csdnimg.cn/img_convert/89ac51c3de0a687805b1b73a2c4ab1ef.png)
継承メカニズムは、親クラスの sum1 メソッドを実行します。
![](https://img-blog.csdnimg.cn/img_convert/0385586fd9d3cdbdbd31e8483e3680a6.png)
そこで質問ですが、ここでの i はサブクラスを使用するのでしょうか、それとも親クラスを使用しますか?
属性の動的バインディング メカニズムはなく、属性が宣言される場所と使用される場所 (現在のクラスを使用)
ここでの i は親クラスで宣言されているため、親クラスの i 属性が選択され、結果は 20 になります。
2. 多態性配列
意味:
配列の定義型は親クラス型ですが、実際に保存される要素型はサブクラス型です。
人の親クラス:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/** * 多态数组父类 */ public class Person {
private String name; private int age; public Person(String name, int age) {
this .name = name; this .age = age; } public String getName() {
return name; } public void setName(String name) {
this .name = name; } public int getAge() {
return age; } public void setAge( int age) {
this .age = age; } public String say() {
return name + '\t' + age; } } |
学生のサブクラス:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** * 多态数组学生子类 */ public class Student extends Person{
private double score; public Student(String name, int age, double score) {
super (name, age); this .score = score; } // 重写父类的say方法 public String say() {
return super .say() + '\t' + score; } } |
教師のサブクラス:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/** * 多态数组教师子类 */ public class Teacher extends Person {
private double sal; public Teacher(String name, int age, double sal) {
super (name, age); this .sal = sal; } public double getSal() {
return sal; } public void setSal( double sal) {
this .sal = sal; } public String say() {
return super .say() + '\t' + sal; } } |
多態性配列の使用をテストします。
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class Test {
public static void main(String[] args) {
// 多态数组的使用 Person[] persons = new Person[ 5 ]; persons[ 0 ] = new Person( "dahe" , 20 ); persons[ 1 ] = new Student( "wangwei" , 11 , 100 ); persons[ 2 ] = new Student( "zhangsan" , 12 , 60 ); persons[ 3 ] = new Teacher( "wang" , 33 , 15000 ); persons[ 4 ] = new Teacher( "li" , 55 , 25000 ); // 循环遍历多态数组,调用say方法 for ( int i = 0 ; i < persons.length; i++) {
String out = persons[i].say(); // 动态绑定机制,编译类型永远都是Person // 运行类型是根据实际情况由JVM机决定 System.out.println(out); } } } |
出力:
ダーヘ 20
王威 11 100.0
張三 12 60.0
王 33 15000.0
李 55 25000.0
3. 多態性配列の高度な使用法
Teacher サブクラスに新しい教授法が追加されました。
?
1 2 3 |
public void teach() {
System.out.println( "老师:" + getName() + "正在讲课!" ); } |
Student サブクラスには新しい学習メソッドが追加されました。
?
1 2 3 |
public void study() {
System.out.println( "学生:" + getName() + "正在学习!" ); } |
それでは、多態性配列を通じてサブクラスに対応する固有のメソッドにアクセスする方法はあるのでしょうか? 実際、これは、instanceof を賢く使用することで解決できます。
回避策として、多態性配列のループ操作を変更します。
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// 循环遍历多态数组,调用say方法 for ( int i = 0 ; i < persons.length; i++) {
String out = persons[i].say(); // 动态绑定机制,编译类型永远都是Person // 运行类型是根据实际情况由JVM机决定 System.out.println(out); if (persons[i] instanceof Student) {
// 向下转型 Student student = (Student) persons[i]; student.study(); } else if (persons[i] instanceof Teacher) {
Teacher teacher = (Teacher) persons[i]; teacher.teach(); } } |
出力:
ダーヘ 20
ワンウェイ 11 100.0
学生: ワンウェイは勉強しています!
張三 12 60.0
生徒: 張三は勉強しています!
王 33 15000.0
先生: 王先生が講義中です!
li 55 25000.0
先生: li が講義中です!
これで完了です。ポリモーフィック配列は強力で完璧です。
4. 多態性パラメータ
メソッド定義の仮パラメータの型は親クラスの型であり、実際のパラメータの型はサブクラスの型であることが許可されます。
次に、次の多態性パラメーターの使用方法を示します。
父親:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
/** * 多态参数 - 父类 */ public class Employee {
private String name; private double sal; public Employee(String name, double sal) {
this .name = name; this .sal = sal; } public String getName() {
return name; } public void setName(String name) {
this .name = name; } public double getSal() {
return sal; } public void setSal( double sal) {
this .sal = sal; } // 得到年工资的方法 public double getAnnual() {
return 12 * sal; } } |
従業員のサブクラス:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** * 多态参数 - 子类员工 */ public class Worker extends Employee{
public Worker(String name, double sal) {
super (name, sal); } public void work() {
System.out.println( "普通员工:" + getName() + "正在工作!" ); } public double getAnnual() {
return super .getAnnual(); } } |
マネージャーのサブクラス:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/** * 多态参数 - 经理子类 */ public class Manager extends Employee{
private double bonus; // 奖金 public Manager(String name, double sal, double bonus) {
super (name, sal); this .bonus = bonus; } public double getBonus() {
return bonus; } public void setBonus( double bonus) {
this .bonus = bonus; } public void manage() {
System.out.println( "经理:" + getName() + "正在管理!" ); } @Override public double getAnnual() {
return super .getAnnual() + bonus; } } |
テストして、さまざまなポジションの従業員の年収を調べてみましょう。
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * 多态参数测试类 */ public class Test {
public static void main(String[] args) {
Worker zhang = new Worker( "张工" , 1000 ); Manager milan = new Manager( "milan" , 5000 , 2000 ); Test test = new Test(); test.showEmpAnnual(zhang); test.showEmpAnnual(milan); } // 获取员工的年薪,采用多态参数 public void showEmpAnnual(Employee e) {
System.out.println(e.getAnnual()); } } |
出力:
12000.0
62000.0
5. 多態性パラメータの高度な使用法
上記の多態性パラメーター コードを改善しましょう。入力が従業員の場合は独自の work メソッドを呼び出し、入力がマネージャーの場合は独自の manage メソッドを呼び出します。
次のメソッドを追加します。
?
1 2 3 4 5 6 7 |
public void testWork(Employee e) {
if (e instanceof Worker) {
((Worker) e).work(); // 向下转型 } else if (e instanceof Manager) {
((Manager) e).manage(); } } |
テスト:
?
1 2 |
test.testWork(zhang); test.testWork(milan); |
出力:
一般従業員:張さんは働いています!
マネージャー: ミランが管理しています!