一番かんたんなJava入門

これからJavaを始めようという人の為の超入門サイトです。丁寧、簡単にこだわった解説なので初心者にぴったりです

【Java】 abstractって何?

time 2017/02/20

 前回まで継承について説明してきました。今回は継承と関係の深いabstractについて説明します。

 継承が分かっていないとabstractは何のこっちゃ分からないと思うので、継承何それ?な人は継承って何?から読み直すようにして下さい。

sponsored link

abstractなメソッド

 abstractというのは、メソッドの修飾子として使われます。

 例えばメソッドを定義する時にvoidを付けることで、「このメソッドは戻り値を返さないメソッドです」ということを指定できるのと同じように、メソッドを定義する時にabstractを付けることで、「このメソッドはabstractなメソッドですよ。」と指定するわけです。

例)abstractvoidなメソッドを定義しています↓

abstract void method();

 
 では、abstractなメソッドというのは、どういうメソッドなのか?

 それは処理内容がまだ定義されていないメソッドです。

 肝心の処理内容はまだ決めていません。っていう状態のメソッドを定義したい時に使うのがabstractなんです。

 先程のabstractメソッドの定義部分をよく見て下さい。↓

abstract void method();

 メソッドを定義しているにも関わらず処理内容を定義する為の{ }がなく、;(セミコロン)で終わっているのが分かると思います。
 abstractを付けてこのようなちょっと変わった書き方をすることで、処理内容が未定義のメソッドを定義することができるわけです。

 じゃあ、その処理内容が決まっていないメソッドを使う(呼ぶ)とどうなるの?と心配になりますが、abstractメソッドは実はそのままでは使うことはできません。

 abstractメソッドは継承、およびオーバーライドされることが大前提のメソッドなんです。

abstractなクラス

 abstractの具体的な使い方や、その意味を理解するために、例としてHumanクラスを作ってみます。

Human.java

public class Human {
    void eat(){
        System.out.println("ご飯を食べました");
    }
}

 
 eatメソッドをメンバとして持つHumanクラスを書いてみました。このHumanクラスをインスタンス化して、食べさせると以下のようなコードになります。

Main.java

public class Main {
    public static void main(String[] args) {
        Human human = new Human();
        human.eat();
    }
}

実行結果↓

 このHumanクラスにabstractなメソッドを追加してみます。

Human.java

public class Human {
    void eat(){
        System.out.println("ご飯を食べました");
    }
    abstract void work();
}

 これでHumanクラスはabstractなメソッド(work)を持つクラスになりました。

 abstractなメソッドをメンバーとして持つクラスは、クラス自体にもabstractを付ける必要があります

Human.java

public abstract class Human {
    void eat(){
        System.out.println("ご飯を食べました");
    }
    abstract void work();
}

※abstractなメンバーを持っているのに、classの宣言部分にabstractを付けずにいるとコンパイルエラーになります。

 さて、これでHumanクラスはabstractなクラスになりました。

 さあ、このHumanクラスをインスタンス化してみましょ・・とは出来ません。

 abstractなクラスはインスタンス化することは出来ません。そりゃそうです。内容が未定義のメソッドというわけの分からんものがある状態でインスタンス化なんてできるはずがありません。

 abstractなクラスというのは継承元(親クラス)として使う為に存在するんです。ちょっと言ってることが分からないかも知れませんが、だんだん分かってくるので、実際にHumanクラスを継承したProgrammerクラスを書いてみましょう。

Programmer.java

public class Programmer extends Human {

}

 eclipse等のIDEを使って実際コードを書くと、abstractなクラスを継承した時点で、クラス名Programmerの部分に赤線が引かれコンパイルエラーになります。その赤線部分をクリックするとそのエラーを回避するための2つの方法が提示されます。

 Add unimplemented methods(未定義のメソッドを追加する)をクリックすることで、親クラス(Humanクラス)ではまだ内容が未定義だったworkメソッドが、Programmerクラスのメンバーメソッドとして自動的に挿入されます。

Programmer.java

public class Programmer extends Human {

    @Override
    void work() {
        // TODO Auto-generated method stub
		
    }

}

 ↑こんな風にworkメソッドの中身を定義する為のコードが自動的に挿入されると思うので、定義部分を書いてしまいましょう。

Programmer.java

public class Programmer extends Human {
    @Override
    void work() {
        System.out.println("プログラミングをしました");
    }
}

※コメント部分は消しています。

 さて、これで仕事をするProgrammerクラスが出来ました。実際にインスタンス化して仕事させてみましょう。

Main.java

public class Main {
    public static void main(String[] args) {
        Programmer programmer = new Programmer();
        programmer.eat();
        programmer.work();
    }
}

実行結果↓

 ちゃんと仕事していますね。

抽象クラスと抽象メソッド

 ・・・で?

 ・・・何をそんなに回りくどいことをしてるの??

 と思う気持ちも分かりますが、もう少し辛抱して読み進めて下さい。

 この一連のabstractによって何をしたのかと言うと、「人間ならば何でも良いから仕事をするんだぞ!」というルールを作ったわけです。

 上記の例ではProgrammerですが、例えばDoctorクラスを書くなら、以下のように書くことができます。

Doctor.java

public class Doctor extends Human {
    @Override
    void work() {
        System.out.println("患者を診ました");
    }
}

 

 同様に、Teacherクラスなら以下のように書けます。

Teacher.java

public class Teacher extends Human {
    @Override
    void work() {
        System.out.println("生徒に勉強を教えました");
    }
}

 

 これらのクラスはHumanクラスを継承しているので、人間(Humanオブジェクト)です。もう継承の本質を理解していますよね?

Child is Superです。

 プログラマーも医者も先生も、皆、人間です。人間である以上、働かねばならないんです。

 つまり、abstractという仕組みを使って、「Humanオブジェクトである以上はworkメソッドを持つ」という約束事を作ったわけです。

 abstractなクラスのことを抽象クラスと表現したりします。抽象クラスは自身がインスタンス化する為に存在するのではなく、親クラスとして子クラスを生む為だけに存在します。

 実際にインスタンスを作るのは、抽象クラスを継承した子クラスが担います(上記の例で言うProgrammerクラス、Doctorクラス、Teacherクラス)。


※通常、継承の矢印は子から親に向けて書きますが、理解しやすいようにあえて逆に書いてますのでご注意を。

 Humanオブジェクトである以上はworkメソッドを実装するべきなのですが、その実行内容(お仕事内容)に関してはプログラマーなのか医者なのか先生なのかによって様々な違いがあるので、Humanクラスでその仕事内容まで定義することはできません。

 そこで、workメソッドをabstractなメソッド(抽象メソッド)にすることによって、「中身はそれぞれで定義したらいいけど、人間である以上はworkメソッドが呼ばれたら働けるようにしておきなさいよ。」という状態を強制することができるわけです。

 抽象クラスは、いわばクラス設計の雛形として使う為に書くわけです。人間とはこうあるべきだと。

何の為のabstract?

 で、結局、abstractって何の役に立つの?

 と感じる人もいると居ると思います。その感覚はある意味で正しいと思います。

 別にabstractなんて使わなくても、単にHumanクラスを継承するクラスには必ずworkメソッドを書けばいいだけの話ですから。

 以下はabstractを使わずにProgrammerクラスにworkメソッドを追加しているだけですが、動作は全く同じです。

Human.java

public class Human {
    void eat(){
        System.out.println("ご飯を食べました");
    }
}

Programmer.java

public class Programmer extends Human {
    @Override
    void work() {
        System.out.println("プログラミングをしました");
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Programmer programmer = new Programmer();
        programmer.eat();
        programmer.work();
    }
}

実行結果↓

 このように、abstractが無くても動作的には何の問題もありません。むしろこの場合はHumanクラスをインスタンス化することも可能です(出来たほうが良いかどうかはさて置き)。

 では、なぜabstractを使うのかと言うと、ただ決められたクラス設計を正確に実現する為です。

 「Humanクラスを継承するクラスには必ずworkメソッドを実装せよ」と紙に書いて貼っておくのではなく、Humanクラスを継承するクラスにはworkメソッドがないとコンパイルが通らないという状態を作る為にabstractを使うんです。そうすることによって、設計された決まり事をより正確に実現することができるわけです。

 賢明な読者様ならお気づきだと思いますが、あくまで重要なのはクラス設計です。abstractはその決められたクラス設計を正確に漏れなくコーディングする為のツールみたいなものであって、もしクラス設計自体に問題があれば何の役にも立ちませんし、むしろ邪魔になるかも知れません。

 なので、自分でabstractを使いこなしてコーディングするというのは、より良いクラス設計が出来ないと無理なので、ちょっとハードルは高めです。

 初心者としては、とりあえず抽象クラスというのは、それ自身がインスタンス化される為に存在するのではなく、その子クラス達の雛形として存在しているということを理解しておけば良いと思います。

 abstractを上手く使って、効率のいいクラス設計を自分で出来るようになりたい人は、デザインパターンについて学んでみてください。こういうのが理解できるとかなりレベルアップするはずです。

分からないことはプロのエンジニアに聞いてみてください↓

sponsored link

Androidアプリを作ろう

コメント

  • シリーズ?通して読ませていただいてます。

    他のサイトと目線のようなものが違うのかどの記事を読んでもわかりやすくてかなり助かっています!
    曖昧に理解してたことがすっきりとわかるので読んでてとても楽しいです!

    次の更新も楽しみにしています。
    よければ例外処理なんて書いていただけると嬉しいなって・・

    by 匿名 €2017/03/02 15:17

  • >匿名さん
    嬉しいコメントありがとうございます。
    例外はいろいろあって難しいですよね。(^^;)

    例外の前にインターフェイスについても解説したいなと思っています。
    例外まで辿り着けるように頑張りますので、今後ともよろしくです。

    by Nobuo@管理人 €2017/03/04 15:41

down

コメントする



一番かんたんなJava入門

Androidアプリの作り方

忘備録

私の作ったAndroidアプリ

おすすめ入門書

おすすめプログラミングスクール

そうだ!プロに聞いてみよう

管理人

Nobuo_CREATE

Nobuo_CREATE

WordPressテーマPrinciple、マテリアルを作ったり、Androidアプリを作ったり、Java入門サイトを作ったり、本を書いたりしています。どうぞよろしく。 [詳細]



sponsored link

オススメ書籍

[オススメpoint]

 この本は全く何も分からない初心者の方にお勧めです。プログラミングをするには覚えなければならない事が無茶苦茶いっぱいありますが、この本は教えてくれる順番、その構成が素晴らしいです。RPGのゲームを作るというストーリーにのっとってちょっとずつ難しいことを教えてもらえます。
 無機質で膨大なデータが載っているような本は読む気にならないという方は、こういうストーリー仕立ての本でチャレンジしてみてはいかがでしょうか?(注:RPGを作る為の本ではありません。)

[オススメpoint]

 ある程度、Javaを読み書きできるようになったら、オブジェクト指向について学ぶべきです。本書は、抽象的で分かったような分からんようなオブジェクト指向について、非常に分かりやすい例を出して説明してくれています。オブジェクト指向とは何なのか?という本質を掴むのにこれほど適した本はないと思います。オブジェクト志向の理念を理解できれば、より効率のいいコードをより楽に書けるようになるはずです。Java上級者を目指すなら必読の一冊!

只今、急拡大中

JavaからのRuby on Rails入門

JavaからのRuby on Rails入門

大人気!COBOLからのJAVA