はじめに
この実験では、アクセス修飾子と継承について学びます。異なる修飾子を使用すると、アクセスレベルが異なります。Java における継承は、生物学的な継承と同じように、子孫が親の特徴を引き継ぎ、ある意味で異なる振る舞いをすることができます。
この実験では、アクセス修飾子と継承について学びます。異なる修飾子を使用すると、アクセスレベルが異なります。Java における継承は、生物学的な継承と同じように、子孫が親の特徴を引き継ぎ、ある意味で異なる振る舞いをすることができます。
今のところ、私たちは既にいくつかのコードを書いてきました。前の実験では、クラスを書きました。public
やprivate
のようないくつかの修飾子があります。では、これらの言葉は何を意味するのでしょうか?
Java は、クラス、変数、メソッド、コンストラクタのアクセスレベルを設定するための多くのアクセス修飾子を提供しています。4 つのアクセスレベルは以下の通りです。
Java は、さまざまな方法で動作を微調整するための多くの非アクセス修飾子を提供しています。
static
変数のコピーが 1 つだけ存在します。final
変数は明示的に 1 回だけ初期化できます。final
メソッドは、サブクラスによってオーバーライドできません。クラスはfinal
として宣言されることで、サブクラス化されることを防ぎます。abstract
クラスは決してインスタンス化できません。abstract
メソッドは、実装が宣言されていないメソッドです。synchronized
とvolatile
修飾子は、スレッドと関連付けて使用されます。例:
/home/labex/project/modifierTest.java
ファイルに以下のコードを書きます。
public class modifierTest {
// static 変数はクラスが読み込まれるときに初期化されます。
public static int i = 10;
public static final int NUM = 5;
// 非 static 変数はオブジェクトが作成されるときに初期化されます。
public int j = 1;
/*
* ここに static コードブロックがあります。これはクラスが読み込まれるときに実行されます。
* 新しいオブジェクトを作成しても、このブロックは再度実行されません。1 回だけ実行されます。
*/
static{
System.out.println("this is a class static block.");
}
public static void main(String[] args)
{
System.out.println("this is in main method");
// 変数 i にアクセスして変更することができます。
modifierTest.i = 20; //obj.i = 20 と同じ
System.out.println("Class variable i = " + modifierTest.i);
// 変数 NUM にアクセスすることはできますが、変更することはできません。
// HelloWorld.NUM = 10; これはエラーになります。NUM は final で、変更できません。
System.out.println("Class variable NUM = " + modifierTest.NUM);
// 新しいオブジェクトを作成します。
modifierTest obj = new modifierTest();
// クラスとオブジェクトの両方を使って static メソッドと static プロパティにアクセスできます。
obj.staticMethod(); //modifierTest.staticMethod() と同じ
// 変数 j にはこのようにアクセスできません。modifierTest.j
System.out.println("Object variable j = " + obj.j);
}
// コンストラクタ。新しいオブジェクトが作成されるときにのみこれが呼び出されます。
public modifierTest(){
System.out.println("this is in object's constructor.");
}
public static void staticMethod(){
System.out.println("this is a static method");
}
}
出力:
以下のコマンドを使ってmodifierTest.java
ファイルを実行します。
javac /home/labex/project/modifierTest.java
java modifierTest
出力を見てください。
this is a class static block.
this is in main method
Class variable i = 20
Class variable NUM = 5
this is in object's constructor.
this is a static method
Object variable j = 1
多くの場合、私たちはクラスを書いてきました。そして、そのクラスのコードを少しだけ修正するだけで新しいクラスを書く必要があり、それらは論理的にいくつかの関係があります。ここでは継承を使うことができます。継承を実現するには、キーワードextends
を使います。サブクラスはスーパークラスのすべてのアクセス可能なプロパティとメソッドを継承し、サブクラスには独自の特殊なものも持てます。サブクラスでは、public
またはprotected
としてスーパークラスで宣言されたものにアクセスできますが、private
のものには直接アクセスできません。例を見てみましょう。継承構造は図のように表示されます。マルチレベル継承(水平方向)または階層型継承(垂直方向)を実装できます。
例:
/home/labex/project/inheritanceTest.java
ファイルに以下のコードを書きます。
class Animal{
// 私はどんな種類の動物か。
private String species;
private int age = 8;
public Animal(){
System.out.println("Animal's constructor");
}
public void grow(){
// このクラスでは、private プロパティに直接アクセスできます。
System.out.println("I'm "+ this.age + " years old, " +"I grow up.");
}
}
class Dog extends Animal{
private String color;
// このクラスでは、スーパークラスの private 属性にアクセスできませんが、grow() は問題ありません。
public Dog(){
System.out.println("Dog's constructor");
}
public void run(){
this.grow();
System.out.println("I'm dog, I can run.");
}
}
class Bird extends Animal{
private double weight;
public Bird(){
// 明示的にスーパークラスのコンストラクタを呼び出す場合、ここでは最初の行にしなければなりません。
// super();
System.out.println("Bird's constructor");
}
public void fly(){
this.grow();
System.out.println("I'm bird, I can fly.");
}
}
public class inheritanceTest{
public static void main(String[] args){
Dog dog = new Dog();
dog.run();
Bird bird = new Bird();
bird.fly();
}
}
出力:
以下のコマンドを使ってinheritanceTest.java
ファイルを実行します。
javac /home/labex/project/inheritanceTest.java
java inheritanceTest
出力を見てください。
Animal's constructor
Dog's constructor
I'm 8 years old, I grow up.
I'm dog, I can run.
Animal's constructor
Bird's constructor
I'm 8 years old, I grow up.
I'm bird, I can fly.
この出力を見ると、混乱するかもしれません。心配しないでください。なぜか説明します。new
を使ってサブクラスのオブジェクトを作成すると、デフォルトで最初に継承木構造の「上から下」にスーパークラスのデフォルトコンストラクタを呼び出し、最後に自分自身のコンストラクタを実行します。スーパークラスのコンストラクタは、super
キーワードを使って明示的に呼び出すことができますが、それがあるコンストラクタの最初の文でなければなりません。super
キーワードは、階層構造において呼び出し元のクラスの直上のスーパークラスを指します。
アクセス修飾子を使うことで、安全なコードを書き、詳細を隠し、アクセス制御を実現できます。他のユーザーは、メソッドの詳細な実装方法を知る必要はありません。私たちは他の呼び出し元にインターフェイスを提供します。アクセス修飾子については、Java のソースコードライブラリを読んで、どのような違いがあるかを理解してください。継承については、階層構造を覚えておいてください。これはクラス間の関係です。