質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.21%

へthisとは何をしてくれるものですか。

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,232

pancy

score 11

javaの文の中によく出てくるthisとは何をしてくれているんでしょうか。
この文章ではなにを意味しているんでしょうか。

コードclass ClassA {
    private int a;

    public ClassA(int a) {
        this.a = a;//←←←1
    }

    public int getA() {
        return this.a;//←←←2
    }
}
class ClassB {
    private int b;

    public ClassB(int b) {
        this.b = b;//←←←3
    }

    public int getB() {
        return this.b;//←←←4
    }
}

この二つのクラスを継承したClassABを作りたい場合を考えてみましょう。↓のようにできれば良いのですが、これはできません。

class ClassAB extends ClassA, ClassB {
...
}

ClassBのinterfaceを作り、実装する

次に、擬似的な多重継承のためにClassBのインタフェースを作ります。インタフェースとは、抽象メソッドしか持たない抽象クラスのようなものです(違いについては後記)。

interface InterfaceB {
    public int getB();
}
「クラスを継承する」のに対して「インタフェースを実装する」と言います。クラスを多重継承することはできませんが、インタフェースは多重実装することができます(抽象メソッドしか持たない抽象クラスを多重継承することはできませんが、インタフェースは多重実装できるという意味で抽象メソッドしか持たない抽象クラスと異なります)。

インタフェースは抽象メソッドしか持たないことが保障されているので、メソッド名の重複が起こっても、その処理の方法を必ずプログラマが記述することになります。


ClassBはInterfaceBを実装して次のようにします(implements InterfaceBが増えただけ)。

class ClassB implements InterfaceB {
    private int b;

    public ClassB(int b) {
        this.b = b;//←←←5
    }

    public int getB() {
        return this.b;//←←←6
    }
}

ClassAB(ClassAとClassBを多重継承したクラス)

まず解説より先に多重継承のソースを示します。

class ClassAB extends ClassA implements InterfaceB {
    // 多重継承したいClassBのインスタンスを保持する。
    private ClassB instanceB;

    public ClassAB(int a, int b) {
        super(a);

        // ClassBのインスタンスを、与えられた引数で生成。
        this.instanceB = new ClassB(b);//←←←7
    }

    // InterfaceB#getBメソッドを実装する必要がある。
    // 動作の中身はinstanceB(ClassB)に完全に任せてしまう。
    public int getB() {
        return this.instanceB.getB();//←←←8
    }
}
やっていることは、

InterfaceBを実装
ClassBのインスタンスをprivateフィールド(instanceB)に保持
メソッドの中身はinstanceBに丸投げ
です。

以下、順に解説します。


InterfaceBを実装

ClassABにはInterfaceBを実装させます。インタフェースはいくつでも実装できるので、ClassAを継承していようがInterfaceBを実装することができます。

class ClassAB extends ClassA implements InterfaceB {

ClassBのインスタンスをprivateフィールド(instanceB)に保持

次に、多重継承したいクラス(この場合ClassB)のインスタンスを保持するprivateフィールドを作成します。

// 多重継承したいClassBのインスタンスを保持する。
private ClassB instanceB;

メソッドの中身はinstanceBに丸投げ

あとは、すべてをinstanceBに丸投げしてしまいます。例えば、ClassABで実装しなければならないgetBメソッドは

public int getB() {
    return this.instanceB.getB();//←←←9
}
です。instanceBに仕事をさせて、その結果を返しているだけです。この例ではInterfaceBが持っているメソッドが一つしかありませんが、もし仮に10個のメソッドがあれば、これと同じような丸投げの処理を10個書きます。


このようにすれば、InterfaceBのメソッドをすべて持つことを強制された、しかし、その動作はClassBによって決められたClassABを作ることができます。見かけ上は、ClassBを継承しているのと同じです*1。


実行例

ClassABは次のようにして使えます。外から見ると、まるでClassBも継承されているようです。

public class MultipleInheritance {
    public static void main(String[] args) {
        ClassAB instanceAB = new ClassAB(100, 200);

        System.out.println(instanceAB.getA()); // 100と表示
        System.out.println(instanceAB.getB()); // 200と表示
    }
}

参考にしたサイト

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

thisこのインスタンスを意味するキーワードです。
例えばコンストラクタ(1,3,5,7が該当)では、フィールドと引数に同じ変数名aが使われていますが、
this.aとすることでインスタンスのフィールドであることを明示的に示せます。

それ以外のthisも「このインスタンス自身」を指し、これに続いて.フィールド.メソッド()が続くことで、「このインスタンス自身のフィールドやメソッド」であることを明示的に示しますが、こういう場所で書いてもさほど意味がありません。thisなしでも同じ意味を示しますので。

ではどういうときに使うか?それは、引数に同じクラスの別のインスタンスが入るような状況です。具体的には

  • equals
    引数にオブジェクトを取り、そのオブジェクトが自分と等しいか判定するメソッド
    基本的にオブジェクト内のフィールドが同じ値かを比較するが、下記のように同名のフィールドを比較することになるため、明確に「このオブジェクトのフィールド」であることを示すためにthisをつけることがある
//ClassA内のメソッドとして説明
public boolean equals(Object o) {
    //instanceofなどの判定が入るがここでは本質ではないため省略
    ClassA x = (ClassA)o;
    return this.a == x.a;
}
  • ComparableインタフェースのcompareTo
    引数に自分と同じ型のオブジェクトを取り、自分と引数どちらが小さいか(順番に並べるとき、どちらが先に並ぶか)を判定するメソッド
    これも多くは同じ名前のフィールドを比較するため、thisで違いを明確化する際に使うことがある
//同じくClassAのメソッドとして説明
public int compareTo(ClassA another) {
    if (this.a < another.a) {
        return -1;
    } else if (this.a > another.a) {
        return 1;
    } else {
        return 0;
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

あまり詳しくないのですが雰囲気だけお伝えします。

thisとは、オブジェクト生成したモノ自身のことを指しています。

この場合
x = new KeisyoA();
とかで(javaの書き方が違かったらすいません)新しくオブジェクトを生成した場合
このxというオブジェクトはKeisyoAgetAというメソッドを持っています。
KeisyoA内でthis.aでアクセスした時は自分自身、つまりxのもつaという変数(プロパティ)にアクセスしていることになります。

別のオブジェクト(y)を生成したりすると
yのメソッドの中でxのプロパティにアクセスしたりすることもありますので
その場合の区別にもなりますね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

インスタンスには外側と内側を分ける境界線があります。
外側からは参照型変数を使ってインスタンス内のメソッドやフィールド変数にアクセスします。
内側からはthisを使ってインスタンス内のメソッドやフィールド変数にアクセスします。内側からのアクセスの場合はthisを省略できますが、同名の変数がある場合は明確に識別するためにthisをつけなければいけません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

this

意味は皆さんが回答していらっしゃる通りです。
ひと言で言うと、thisとは「このインスタンスの」という意味になります。

わかりにくいと思うので、thisをつけた場合とつけなかった場合、それぞれが何を示すか考えてみます。

class ClassA {
    private int a; // フィールドの a

    public ClassA(int a /* 引数の a */) {
        this.a = a;//←←←1
    }
// 下に続く


上のコードは質問コードの抜粋です。ここには2行目と4行目に同じ名前の変数int aがありますね。
//←←←1 の関数に注目します。この関数の中では、aと書いたらどっちのaのことを言ってるの?というのが今回の問題です。
結論を書くと、単なるaは4行目の引数のint aを示し、this.aは2行目のフィールドのint aを示します。今回の例のように、変数名がかぶる場合、引数のほうが優先されます。だから、フィールドのint aを参照したい場合は、thisをつけて「このインスタンスのint a」だとはっきりさせる必要があるのです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る