Javaを10(継承、class object、継承、オブジェクト)に設定

48154 ワード

継承(続き)


Creating a subclass


コンストラクタの問題->オブジェクトの作成時に呼び出されるコンストラクタは、C++のイニシエータと同じです.
コンストラクション関数がない場合はdefault constructorが呼び出され、スーパークラスのコンストラクション関数が呼び出されます.
class Employee{
	private String name;
    private int salary;
    public Employee(){
		name="NoName";
        salary=50000;
}
	public String getname() {return this.name;}
    public int getSalary() {return this.salary;}
}

class Manager extends Employee{
	private int bonus;
    public void setBonus(int bonus) {this.bonus=bonus;}
    public int getSalary() {return super.getSalary() +this.bonus;}
}
サブクラスでconstructorが呼び出されるとsuperclassのconstructorが呼び出されると、サブクラスのconstructorが実行されます.そこで,整理すると,スーパークラス構造関数は無条件に呼び出される.
class Employee {
	private String name;
	private int salary;
	public Employee() {
		this.name = "NoName";
		this.salary = 50000;
	}
	public void setName(String name) { this.name = name; }
	public String getName() { return this.name; }
	public int getSalary() { return this.salary; }
}
class Manager extends Employee {
	private int bonus;
	public Manager() {
		super.setName("NoName(Manager)");
		bonus = 10000;
	}
	public void setBonus(int bonus) { this.bonus = bonus; }
	public int getSalary() { return super.getSalary() + this.bonus; }
}
superclassのコンストラクション関数がパラメータを受け取ったらどうなりますか?サブクラスがsuperclassのコンストラクション関数を呼び出さない場合、エラーが発生します.サブクラスはパラメータのないコンストラクション関数を呼び出そうとしているからです.したがって、次のコードに示すようにsuper(name,salary)を呼び出す必要があります.
class Employee {
	private String name;
	private int salary;
	public Employee(String name, int salary) {
		this.name = name;
		this.salary = salary;
	}
	public String getName() { return this.name; }
	public int getSalary() { return this.salary; }
}
class Manager extends Employee {
	private int bonus;
	public Manager(String name, int salary) {
    //필수적으로 superclass의 constructor을 호출하여 주어야 한다.
		super(name, salary);
		bonus = 10000;
	}
	public void setBonus(int bonus) { this.bonus = bonus; }
	public int getSalary() { return super.getSalary() + this.bonus; }
}

Detour:Implicit Constructor(またはDefault Constructor)


クラスにコンストラクション関数が含まれていない場合は、Implicitコンストラクション関数と呼ばれます.Implicit constructorにはパラメータがなく、スーパークラス構築関数しか呼び出せません.
コンストラクション関数が含まれている場合は、明示的コンストラクション関数と呼ばれ、Implicitコンストラクション関数は呼び出されません.
class Employee {
	private String name;
	private int salary;
}
class Employee {
	private String name;
	private int salary;
	public Employee(String name, int salary) {
		this.name = name;
		this.salary = salary;
	}
}

したがって,パラメータ値を明示的な構造関数が存在するクラスに渡さないとエラーが発生する.

Dynamic method lookup


Employee<-Managerは、次のコードを表します.
Manager boss = new Manager();
Employee empl = boss;
int salary = empl.getSalary(); 
// call getSalary which is defined in both Employee and Manager.

  • スーパークラスとサブクラスは同じ名前の関数です.
    以上のように、スーパークラス変数にサブクラスオブジェクトがある場合にgetSalry()関数が上書きされます.
    JVMでは、動的メソッド検索機能がオブジェクトを追跡します.この部分がC++とJAVAの違いの一つです.C++は、親に仮想宣言されていない限り、変数に無条件に従いますが、JVMはオブジェクトに自動的に従います.

  • 関数がスーパークラスの場合
    もちろん、サブクラスにメソッドが定義されていない場合は、superclassのメソッドが呼び出されます.

  • サブクラスのみがこの関数を持つ場合
    李ギョンウは反対だ.変数はsuperclass変数であるため、変数に優先的に従い、superclassには存在しない関数です.C++と同じ部分と言えます.
  • Employee empl = new Manager("Donald", 100000);
    empl.setBonus(20000);
    上記の状況を考慮することができる.
    Employee empl = new Manager("Donald", 100000);
    if(empl instanceof Manager) {
    	Manager mgr = (Manager) empl;
    	mgr.setBonus(20000);
    }
    System.out.println(empl.getSalary());
    これらの問題を解決するためにinstanceofキーワードを使用します.
    オブジェクトinstancofクラス
    オブジェクトがクラスタイプのキーワードtrue、falseに変換できるかどうかを示します.したがって、上記のManagerオブジェクトを持つEmployee変数をManagerに変換できます.逆に、次の例を見てみましょう.

    上記のように、親を持つ親変数を子変数に変換することはできません.

    Final method


    Final methodは、関数の上書き不可を宣言する方法です.
    class Employee {
    	private String name;
    	private int salary;
    	public Employee(String name, int salary) {
    		this.name = name;
    		this.salary = salary;
    	}
    	public final String getName() { return this.name; } // subclass cannot override this method.
    	public int getSalary() { return this.salary; }
    }
    class Manager extends Employee {
    	private int bonus;
    	public Manager(String name, int salary) {
    		super(name, salary);
    		bonus = 10000;
    	}
    	public void setBonus(int bonus) { this.bonus = bonus; }
    	public String getName() { return "Sir " + super.getName(); } // Error: overriding a final method
    }

    Fincal class


    これはextendsを阻止する方法です.
    final class Employee {
    	private String name;
    	private int salary;
    	public Employee(String name, int salary) {
    		this.name = name;
    		this.salary = salary;
    	}
    	public String getName() { return this.name; }
    	public int getSalary() { return this.salary; }
    }
    class Manager extends Employee {
    ... // Error: cannot inherit a final class
    }
    代表的なString classはFinal classです.

    Abstract method and abstract class

    abstract class Person {
    	private String name;
    	public Person(String name) { this.name = name; }
    	public final String getName() { return name; }
        
    	public abstract int getId();
    }
    上記のように、abstractメソッドを持つクラスはabstractとして宣言する必要があります.
    このようにして作成されたabstract classを受け入れるサブクラスはgetID()のようなabstractメソッドを一般メソッドとして再定義する必要があり、またはサブクラスもabstractである.
    しかし、抽象classはinterfaceに似ているように見えます.どんな違いがありますか.違いは、instance変数とconstructorを持つことです.

    Abstract class


  • Abstraactクラスではオブジェクトを作成できません.

  • Abstractクラスが取得された場合は、抽象メソッドを再定義する必要があります.
  • Protected access

    class Employee {
    	private String name;
    	protected int salary;
    	public Employee(String name, int salary) {
    		this.name = name;
    		this.salary = salary;
    	}
    	public String getName() { return this.name; }
    	public int getSalary() { return this.salary; }
    }
    class Manager extends Employee {
    	private int bonus;
    	public Manager(String name, int salary) {
    		super(name, salary);
    		bonus = 10000;
    	}
    	public void setBonus(int bonus) { this.bonus = bonus; }
    	public int getSalary() { return salary + bonus; } // can access superclass protected variable
    }
    保護は以下の場合には近づけません.
    1.非サブクラスアクセス不可
    2.その他の小包はアクセスできません
    逆に、サブクラスの場合、保護された変数と関数はアクセス可能です.

    Superclass and Interface


    インタフェースは、複数の継承であってもよい.
    Superclassは多重継承できません.これはC++とのもう一つの違いです.
    class Student extends Person, Animal { // Error: cannot extend multiple classes.
    ...
    }
    インタフェースはスーパークラスとともに受信可能である.
    interface Named {
    	default String getName() { return "NoName"; }
    }
    abstract class Person {
    	private String name;
    	public Person(String name) { this.name = name; }
    	public String getName() { return name; }
    	public abstract int getId();
    }
    class Student extends Person implements Named {
    	private int id;
    	public Student(String name, int id) { super(name); this.id = id; }
    	public int getId() { return id; }
    }
    以上のように
    Student s = new Student("Fred", 1729);
    System.out.println(s.getName());
    superclassとinterfaceの両方が持つ関数を呼び出すと、superclassに優先度があります.

    class Object : superclass of all classes


    すべてのクラスはObjectという名前のクラスを継承します.
    class Student {
    ...
    }
    class Student extends Object {
    ...
    }
    上の2つのクラスは同じクラスを継承する場合です.

    この場合、Objectクラスには上記の機能が含まれます.もちろんこれだけではありません.

    class Object: method toString

    class Employee {
    	private String name;
    	protected int salary;
    	public Employee(String name, int salary) { this.name = name; this.salary = salary; }
    	public String getName() { return this.name; }
    	public int getSalary() { return this.salary; }
    }
    クラスが上記のようになった場合
    Employee empl = new Employee("John", 50000);
    System.out.println(empl.getName() + " " + empl.getSalary());
    System.out.println(empl.toString());
    前述したように、オブジェクトの情報はString値を返します.
    Employee empl = new Employee("John", 50000);
    System.out.println(empl.getName() + " " + empl.getSalary());
    System.out.println(empl); // this will print empl.toString()
    ただし、トイストリング()は口紙を使わずにそのまま出力できます.
    また、関数自体を上書きすることもできます.
    class Manager extends Employee {
    	private int bonus;
    	public Manager(String name, int salary) { super(name, salary); bonus = 10000; }
    	public String toString() { return super.toString() + "[bonus=" + bonus + "]"; }
    	public void setBonus(int bonus) { this.bonus = bonus; }
    	public int getSalary() { return salary + bonus; }
    }
    superclass関数を呼び出すことでも使用できます.