クラスにメソッドを定義する

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

このレッスンで分かること

  • インスタンスメソッドは インスタンス.メソッド名() の形で呼び出します、フィールドに this. でアクセス
  • 静的メソッドは クラス名.メソッド名() で呼ぶ、this は使えない
  • 最小例は class Book { String title, author; public String describe() { return this.title + " by " + this.author; } }

クラスにメソッドを定義する とは

クラスに振る舞いを持たせるインスタンスメソッドの定義方法と、static メソッドとの違いを学ぼう。本レッスンでは、クラスにメソッドを定義する の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

クラスにメソッドを定義する

前回までで、class を使ってデータ (フィールド) をひとまとめにし、newインスタンス を作るところまで進みました。今回はそのクラスに 振る舞い を持たせる仕組み、インスタンスメソッド の書き方を学びます。データだけ持っていても料理は作れません。フィールドという「材料」に、メソッドという「調理手順」を組み合わせて、はじめてクラスは生きたオブジェクトになります。

オブジェクト指向では「オブジェクトはデータと振る舞いをひとまとめにしたもの」と説明されます。フィールドが データ、メソッドが 振る舞い の正体だと覚えてください。

インスタンスメソッドとは

インスタンスメソッド とは、new で作ったインスタンスごとに呼び出せるメソッドのことです。book.getDescription() のように、インスタンスの変数 . メソッド名() という形で呼び出します。同じクラスから作ったインスタンスでも、フィールドの値が違えば返ってくる結果が変わる、というのが大事なポイントです。

たとえば Book クラスに titleauthor というフィールドがあって、getDescription() メソッドがその 2 つを組み合わせた説明文を返すとしましょう。book1.getDescription()book2.getDescription() は、同じメソッドを呼んでいるのに、book1book2 の中身に応じて違う文字列を返します。これが「振る舞いがインスタンスに紐づく」という意味です。

ここまで Java で書いてきた Solution.helloWorld() のような呼び方は 静的メソッド (static method) と呼びます。クラスそのものに紐づくメソッドで、インスタンスを作らなくても呼べました。今回学ぶ インスタンスメソッド はそれと対になる概念です。

インスタンスメソッドが活躍するのは次のような場面です。

  • オブジェクトごとに違う情報を返したいbook.getDescription() user.getFullName() product.getTaxIncludedPrice() などインスタンスのフィールドを使った計算
  • オブジェクトの状態を変えたいcounter.increment() cart.addItem(item) のように、内部の値を書き換える操作
  • データと処理をまとめて扱いたい — フィールドとそれを操作するメソッドを 1 つのクラスに置くことで、関心ごとを 1 か所に集約できる

フィールドにアクセスする (this.field)

インスタンスメソッドの中では、this というキーワードを使って自分自身のフィールドにアクセスします。this.title と書けば「いま呼び出されているインスタンスの title」を指します。

Java

public class Book { String title; String author; public String getDescription() { return this.title + " by " + this.author; } }

この Book クラスでは、フィールド titleauthorthis.titlethis.author で参照しています。同じ名前のフィールドが複数のインスタンスに存在しても、this を介すことで「いま呼ばれた当人」の値を正しく取り出せます。

this はメソッドの引数とフィールドの名前がぶつかったときに必須になります。引数と被らないときは省略して title + " by " + author と書いても動きますが、初学者のうちは this. を明示的に付けると「これはフィールド」と一目でわかって読みやすくなります。

呼び出し側のコードでは、newBook を作って、titleauthor をセットしてから getDescription() を呼びます。

Java

public class Main { public static void main(String[] args) { Book book = new Book(); book.title = "Java 入門"; book.author = "著者A"; String desc = book.getDescription(); System.out.println(desc); } }

出力は Java 入門 by 著者A です。getDescription() の中で this.title this.author がそれぞれ "Java 入門" "著者A" に置き換わって連結されています。

メソッドはオブジェクトの「振る舞い」を表現する

インスタンスメソッドの本質は「そのオブジェクトが何をできるか」を表現することです。Book というオブジェクトは「自己紹介できる」(getDescription())、Counter というオブジェクトは「カウントアップできる」(increment())、Cart というオブジェクトは「商品を追加できる」(addItem()) というふうに、メソッド名はそのまま「動詞 + 名詞」でクラスの能力を物語ります。

設計のコツは、メソッド名を見たら何をするかが想像できる名前にすること、そして 1 つのメソッドに詰め込みすぎないことです。doEverything() のような巨大メソッドは保守が大変なので、calculatePrice() formatLabel() のように責任を分けるのが基本です。

メソッドが呼ばれた瞬間の流れを図で見てみましょう。呼び出し元から book.getDescription() を実行すると、いったん主役が Book インスタンスの内部に移り、this.titlethis.author を組み立てて、return で呼び出し元に戻ってきます。

diagram (will load when visible)

この「呼び出し元 → インスタンス → 呼び出し元」というキャッチボールこそが、オブジェクト指向の世界でのメソッド呼び出しのリズムです。

静的メソッドとの違い

静的メソッド (static) とインスタンスメソッド (static なし) の違いは、次のとおりです。

  • 静的メソッドクラス名.メソッド名() で呼ぶ。インスタンスを作らなくても呼べる。this は使えない
  • インスタンスメソッドインスタンス変数.メソッド名() で呼ぶ。先に new でインスタンスを作る必要がある。this で自分のフィールドにアクセスできる
観点静的メソッド (static)インスタンスメソッド
呼び出しクラス名.メソッド名()インスタンス.メソッド名()
事前準備不要new でインスタンスを作る必要あり
this使えない使える (自分自身を指す)
フィールドへのアクセスstatic フィールドのみインスタンスのフィールド可
代表例Math.max(1, 2)book.getDescription()

Math.max(1, 2) のような「ただの計算を呼びたい」場面は静的メソッド向き、book.getDescription() のように「自分のフィールドを使って答えたい」場面はインスタンスメソッド向き、と覚えると判断しやすくなります。

同じクラスの中に、静的メソッドとインスタンスメソッドを両方置くこともできます。main メソッドは典型的な static メソッドで、その中から new Book() でインスタンスを作って book.getDescription() を呼び出す、という組み合わせが定番です。

両者の関係を頭の中で整理しておきましょう。

Java

public class Demo { String name; // インスタンスメソッド: this が使える public String greetInstance() { return "Hello, " + this.name; } // 静的メソッド: this は使えない public static String greetStatic(String who) { return "Hello, " + who; } }

Demo.greetStatic("Java") はそのまま呼べますが、Demo.greetInstance() という書き方はできません。Demo d = new Demo(); d.name = "Java"; d.greetInstance(); のように、先にインスタンスを用意する必要があります。

よくある間違い

インスタンスメソッドを書き始めた頃に、ほぼ全員がぶつかる落とし穴を 3 つ紹介します。

  • static を付けたり外したりを間違える — クラス内のフィールドを使うインスタンスメソッドに static を付けると、non-static field cannot be referenced from a static context というエラーが出ます。逆にユーティリティ的な計算なのに static を外すと、毎回 new してから呼ばないといけなくなり不便です。「フィールドに触るかどうか」で判断しましょう
  • this を使わずに引数とフィールドを混同する — メソッドの引数とフィールドが同じ名前のとき、title = title; と書いても何も起きません (引数が引数に代入されているだけ)。this.title = title; のように、フィールド側だけ this. を付けて区別する必要があります
  • 戻り値の型と return の値がずれる — メソッドの宣言が public String getDescription() なのに return 123; と書くとコンパイルエラーです。戻り値の型と return で返す値の型は必ず一致させてください。何も返さないなら戻り値型を void に変える、というルールも忘れずに

エラーメッセージは敵ではなく味方です。cannot find symbol ならタイポ、non-static field なら static の付けすぎ、incompatible types なら型の不一致、と見分けがつくと修正がぐっと早くなります。

この章のポイント

ここまでの要点 インスタンスメソッドは new 必須、this.field で自分のフィールドに触れる。static メソッドは this が使えず、フィールドに触らない計算向き。フィールドに触るかどうかで使い分ける。

やってみよう

それでは課題に挑戦しましょう。今回は本文で紹介した Book クラスに インスタンスメソッド を 1 つ実装し、そのメソッドを呼んだ結果を返します。手順は次のとおりです。

  1. 右側のエディタを開く
  2. Solution の中の static class Book を確認する (フィールド title author とコンストラクタが用意されている)
  3. Book クラスの describe() メソッドに return this.title + " by " + this.author; を書く
  4. bookDescription(title, author) の中で return new Book(title, author).describe(); のように、インスタンスを作って describe() を呼ぶ
  5. 「実行」ボタンを押して、テストが緑になることを確認する

固定で return "Java 入門 by 著者A"; と書くと 1 ケース目だけは通りますが、それ以外のテストケースで fail します。インスタンスメソッドを実際に経由しないとパスできない作り になっているので、必ず new Book(...).describe() の形で書いてください。

by の前後には半角スペースが 1 つずつ入ります。スペースの有無や全角・半角の違いでテストが落ちるので注意しましょう。

クラスとメソッドが組み合わさると、Java プログラムの表現力は一気に広がります。ここから先は コンストラクタカプセル化継承 と、オブジェクト指向の世界がさらに深まっていきます。まずはこのレッスンで、データと振る舞いを 1 つのクラスにまとめる気持ちよさを体験してみましょう。

よくある質問

Q. メソッドの引数は何個まで書けますか?

A. 言語的には何個でも書けますが、4-5 個を超えると呼び出し側が読みにくくなります。多くなったら関連する引数をクラスや record(Java)/ dataclass(Python)/ オブジェクト(JS)にまとめ、1 つの引数として渡すのがリファクタの定石です。

Q. 戻り値の型 void と他の型はどう使い分けますか?

A. 副作用(DB 更新、画面描画)だけならvoid、計算結果や状態を返すなら具体的な型です。テストしやすさは戻り値ありの方が圧倒的に高いため、純粋関数として書けるところはなるべく値を返す設計にすると良いです。

Q. static メソッドはいつ使いますか?

A. インスタンスの状態に依存しないユーティリティ関数(Math.max など)に向きます。逆にフィールドを使うなら static にせず、インスタンスメソッドにしてください。テスト時に static は差し替えにくいため、依存注入したいなら避けるのが無難です。

次のレッスン

次は インスタンスを作る で、クラスに振る舞いを持たせるインスタンスメソッドの定義方法と、static メソッドとの違いを学ぼう を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. クラスメソッド の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. クラスメソッド とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. Book クラスのインスタンスメソッド describe() を実装すること
  2. bookDescription の中で new Book(title, author).describe() のようにインスタンスメソッドを呼ぶこと (固定文字列の即時 return は不可)
  3. describe()"<title> by <author>" の形 (半角スペース付き) の文字列を返すこと

入出力例

test-cases.txt

bookDescription("Java 入門", "著者A")"Java 入門 by 著者A" bookDescription("Effective Java", "Joshua")"Effective Java by Joshua" bookDescription("確認", "チーム")"確認 by チーム"

ヒント

main.java
main.java
学習モード

メモ

クラスにメソッドを定義する

⌘S で保存