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

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

ただいまの
回答率

88.91%

オブジェクト指向がいまいち理解できません

解決済

回答 7

投稿 編集

  • 評価
  • クリップ 4
  • VIEW 1,963

kobe2018

score 21

オブジェクト指向が分からなくなってきました。

最初にオブジェクト指向を学んだとき、以下のような例がでてきました。

例)Hero(※簡単なRPGをプログラムする際の主人公を意味します)
Heroクラス   :ヒーローが備えるべき性質、行動をまとめたもの(設計図)
Heroインスタンス:実際のヒーロー(人)

これは理解できました。しかし、実際に存在しないものに関してはどうしても違和感があります。
例えば以下のクラスとインスタンス。

例)StringBuilder(文字連結)
StringBuilderクラス   :文字連結に必要な操作をまとめたもの
StringBuilderインスタンス:???

なぜインスタンスをつくるのかわかりません。
Heroの例にたとえると、文字連結の実際の何か???(書いていてわからない)
インスタンスを作らずStaticメソッドだけでいいのではと思ってしまいます。

なぜインスタンスを作るのか、そのインスタンスはどういう役割をしているのか、教えて頂きたいです。

追記
皆さん、回答ありがとうございます。
回答を読んでなるほどと思った反面、もう少し時間を置きたいと思いました。
というのも、いままでしっくり来ていなかったことなので、分かった気になっているだけかもしれないからです。
もう一度、自分の中で本当に理解できているのか、疑問点はないのか確かめたうえで回答およびベストアンサーを決めさせていただきます。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • Zuishin

    2020/07/04 23:37

    わからなくなったのではなく、最初からわかってないのです。
    Hero の例をうのみにしたことにより、わかったつもりになっただけです。
    オブジェクト指向を物にたとえてしまうと、そこで嘘が刷り込まれてしまい、理解にかなり時間がかかるようになる上に完全に抜け出すのがとてつもなく困難になりがちです。
    Hero や犬や車や電子レンジの例は可能な限り早く忘れ、そのような一見わかりやすく見える本は捨てましょう。

    キャンセル

  • m.ts10806

    2020/07/05 08:07

    本だけ読むより実際に設計してみてそれぞれの役割を考えた上でオブジェクトを整備してたくさんコードを組んでいった方が理解か深まるでしょう。
    つまり、本質問のゴールを「オブジェクト志向の本質的理解、使いこなす」に置いてしまうとしばらく解決できないことになります。
    もう少しゴールを近くに置いた方が着実に進むのでは

    キャンセル

回答 7

checkベストアンサー

+4

なぜインスタンスを作るのか、そのインスタンスはどういう役割をしているのか

たとえば、

String hero = "ヒーロ";
String villain = "悪役";

というのがあったときに、hiroとvillainが異なるっていうのは、わかりますか?

当たり前じゃない

って思うでしょ?
そう、当たり前なので解説を見ないのですが、異なる変数に異なるインスタンスを作るって結構あたりまえなのです。

なんでか?っていうと変数は一時的なものが多く、どんどん変更されることが多いため
使い切りになるケースが少ないからです。

StringBuilderも文字列加工は途中の状態がいくつも続くor 続けられるように
インスタンス化して別々の文字列を加工できるように設計されています。

以下のような場合に、複数インスタンスが作れないと面倒くさそうだなというのが、わかると思います。

StringBuilder heroNames = new StringBuilder();
StringBuilder villainNames =  new StringBuilder();
for(story : storys) {
    heroNames.append(story.getHero().name());
    villainNames.append(story.getvillain().name());
}

逆に状態を管理する必要がない。
または複数のインスタンスで共通にしたいものがスタティックで設計されます。

たとえば、String#join なんかは、加工するというか、ただ連結するだけですがスタティックなメソッド
なので、インスタンス化せずに利用できます。

同じクラスでも個々に状態を簡単に管理したいというのがインスタンス化したい。
という理解でよいと思います。

※既回答にありますが、インスタンス化しなくても、そのように設計/実装すれば複数の状態を管理することはできます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/05 00:12

    回答ありがとうございます。
    インスタンスの作成は個々の区別のため、というのがしっくりきました。
    確かにStringBuilderもバッファーを個々に管理できると提示していただいた例では便利だと思います。

    キャンセル

  • 2020/07/06 11:54

    異なる状態を管理したいからインスタンスが必要
    状態とはクラスの(複数の)フィールドの値でメモリに存在する
    状態が矛盾しないように管理したければカプセル化してメソッドを用意する

    「スッキリ…」の文章をよく読むとこんなことが書いてありますが、文章は記憶に残りません。だからこれは絵本ですね。絵本からいきなり大人の会話について行こうとすると悩みます。

    Heroでわかったつもりになっているのは、現実の事物の比喩としてプログラムを見ているからです。オブジェクト指向とは、プログラミング世界のなかの構造、振舞いの比喩です。インスタンス、is-a、has-a構造なのであって現実世界とは関係ありません。

    キャンセル

  • 2020/07/10 22:16

    低評価の理由

    > 異なる変数に異なるインスタンスを作るって結構あたりまえなのです。
    異なる変数に同じインスタンスを作ることもある。そのまえに変数じゃない、それは、オブジェクト。
    また

    StringBuilder heroNames = new StringBuilder();
    StringBuilder villainNames = new StringBuilder();

    このとき、heroNames と villainNames は同じもの。異なるものと説明しているのに、同じものになっている。

    > 変数は一時的なものが多く、
    そんなことはない。プログラム起動時に作って、終了まで使う変数はある。変数ではなくてオブジェクトだが。

    > どんどん変更されることが多いため使い切りになるケースが少ないからです。
    そんなことはない、変更しないで比較対象だけにすることもある。基準値(基準オブジェクト)として。

    > 文字列を加工できるように設計されています。
    設計どうのこうのいうより、StringBuffer の責務を説明したほうがいい。設計うんうんいうのなら、ソースコードがどうなっているのか説明すべき。そうすれば、あぁ、そうして設計しているんだなってわかる。

    > 同じクラスでも個々に状態を簡単に管理したいというのがインスタンス化
    個人の主観であって、実際に実装した人の考え方ではない。

    status を management ? その理由がインスタンスの生成の理由になるとは思えない。

    一番さいご、質問者が

    > もう少し時間を置きたいと思いました。
    私も質問者と同じ気持ちになりました。この回答では理解ができない。

    キャンセル

+2

例)StringBuilder(文字連結)
StringBuilderクラス   :文字連結に必要な操作をまとめたもの
StringBuilderインスタンス:??? 

例えるなら「文字連結業」という職業がクラスで、その技術を身に付けたひとが「文字連結屋さん」というインスタンスです。クラスに書かれたソースコードが「文字連結業」を営むに当たって必要な作業が書かれたマニュアルです。

自分が具体的な手順を知らなくても彼または彼女に頼めば作業を行って結果を返してくれます。
必要なのは頼み方の手順を覚えることだけです。
その代わり「文字連結屋さん」は少なくとも文字連結業として期待される作業は実行できるようになっている必要があります。
行うべき作業を全部自分ひとりで行うのではなく、詳細を知る別のひとに作業を頼むことによって自分がやる作業の詳細を他人任せにすることが出来るようになります。

例え話から話を戻すと、クラス分割して必要な手続きの詳細をクラス内のソースコードに隠すことにして、必要に応じて呼び出し手続きを行うことが出来るようにすれば、その分呼び出し側の負担が減ることになります。
(ただしそうなるためには適切なクラス設計がされているのが前提です。)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/06 21:09

    回答ありがとうございます!
    文字連結屋さんが複数いるのは、それぞれが詳細情報を担っているからというのが、インスタンスの考え方ですね。
    具体例を頂き、ありがとうございます。

    キャンセル

  • 2020/07/10 22:36

    この中の回答では一番だが、最適ではない。
    文字連結屋さんは個性をもてる。という説明がはいれば、良いかと思いました。
    同じもののコピーなら、まじで static だけでいい。

    キャンセル

  • 2020/07/11 01:09

    > インスタンスを作らずStaticメソッドだけでいいのではと思ってしまいます。

    確かに質問者のこの疑問には答えられていなかったですね。
    質問者のコメントを見る限り自ら疑問解決出来たようです。

    キャンセル

+1

なぜインスタンスを作るのか

使いまわしできるように、です。
いかに使いまわしをして楽をするか、に重点を置かれてます。
同じクラスでも、ちょっと変えて使いまわしできるように、少々効率が悪くても、無駄が出ても、とにかく使いまわしで楽ができる、というこをと主眼に置かれています

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

インスタンス や static の使い道は momon-ga さんの回答で既に述べられているので省略します。

加えて、全てのメンバーに対して static をつけて作ったらどう困るか という視点で考えるのも疑問点を整理する1つの手だと思います。試しに架空の StringBuilder を作り、全てのメンバーを static にしてみましょう。

public class StringBuilder{
    private static String value = "";
    public static void append(String s){
        value += s; //説明するために & 実装が楽なのでこうしている
    }

    public static String convertToString(){
        return value;
    }
}
public class Main{
    public static void main(String[] args){
        //"Hello,Takashi."と出したい
        printHello("Takashi"); // Hello,Takashi.

        //"Hello,Masaru."と出したい。しかし…
        printHello("Masaru"); // Hello,Takashi.Hello,Masaru.
    }

    public static void printHello(String name){
        StringBuilder.append("Hello,");
        StringBuilder.append(name);
        StringBuilder.append(".");
        System.out.println(StringBuilder.convertToString());
    }
}

StringBuilder の全てのメンバーが static だった場合、こういうときに困りませんか。
他のクラスに関して同様の違和感を感じた場合も、上記と同じように もし〇〇がなかったらどう困るのか という視点で考えると同様に疑問点が整理できると思います。


疑問点は、インスタンス化しなくてもできるのに、なぜインスタンス化するのか。

先に結論を書けば、オブジェクト指向プログラミングができないからです。オブジェクト指向プログラミングができず、Javaという言語を利用して効率的にコードを組めないからです。

Javaは(クラスベースの)オブジェクト指向プログラミングというプログラミングパラダイムを有しており、当然言語仕様もそれに合わせて作られています。クラスベースなオブジェクト指向言語において、インスタンスの生成は効率的にコードを書くために必要な手段になります。

一方、staticはJavaのMathクラスのような副作用のないメソッドを呼び出す場合においてはstaticである方が便利です。しかし、オブジェクト指向プログラミングを行う場合においては別で、staticなメソッドを呼び出す際はあらゆるオブジェクト指向の機能が使えません。例えば、継承・実装・ポリモーフィズム・カプセル化などが該当します。

オブジェクト指向を使うことのメリットは変更に対して柔軟になることですから、継承・実装・ポリモーフィズム・カプセル化を使わずにstaticで実装するとなると、めちゃくちゃなプログラムが出来上がるでしょう。

「副作用なんて悪いことばかりだし、必要ないじゃん」
「オブジェクト指向なんていらないじゃん」

と思われるかもしれません。(思わなかったらスルーしてください)
確かにその考えもその通りです。

しかし、先述したようにJavaのプログラミングパラダイムがそのようになっていますから、Javaにおいてはオブジェクト指向を利用したコーディングをする方がstaticで対応するよりも効率的です。そうなるよう言語仕様が決まっているのです。

なので、もし kobe2018 さんが本当に「オブジェクト指向なんて抽象的で分かりづらい、全部staticで良いじゃん」と思われるようであれば、プログラミングパラダイムは1つだけではありませんから、色々な言語を触ってみると良いと思います。
(副作用があることが嫌なのであれば、関数型言語はいかがでしょう。私は興味ありますが、触ったことはありません)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/13 14:52 編集

    > インスタンスを生成しないという表現を使わないのはおかしい
    インスタンスの意味が私とBindiさんで違っていたのかもしれません。
    私の中のインスタンスとは、JavaScriptでいうconst hoge = {};であり、C#やJavaでいうHoge hoge = new Hoge();のような表現(どちらもオブジェクト≒インスタンスの生成)のことを想像していました。それがないオブジェクト指向言語とは何なのかと、純粋に疑問を抱いていました。

    キャンセル

  • 2020/07/13 14:53 編集

    > あなたが言う、「差」がわからないのに、クラスベースの方を知りたいと断言する根拠
    これは、単純に kobe2018 さんが、Javaのタグをつけて質問している(= Javaはクラスベース)ので、そうではないかと考えていました。まだクラスベース/インスタンスベースな言語の区別ができるレベルではないでしょうから。

    キャンセル

  • 2020/07/13 14:57 編集

    本人がオブジェクト指向自体をよく知らない状況なので、今回質問しているJava以外の言語(とくに、JavaScriptやPHPのようなインスタンスベース)の回答はきっと分からないんじゃないかなあ…と思ってコメントしてみました。間違っていると書いたつもりも、否定したつもりもありません。(間違っているか厳密に精査はした訳ではありませんが)

    キャンセル

0

「ある数値のリストがあって、奇数と偶数に分けてそれぞれ文字列化して連結しなさい」
StringBuilderが同時に一つしか存在できないと困りますね。

(無理やりひねり出した例なんで普通に+で連結したり、偶数と奇数のリスト2つに分けてから連結したりで回避できますけれども。)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/04 22:54

    回答ありがとうございます。
    つまり、インスタンス化する目的は、複数の文字連結を区別するため。
    インスタンスには情報(フィールド)としてバッファーの位置があり、
    操作(メソッド)としてバッファーへの文字の追加や、追加された文字の連結がある。
    という認識で合ってますでしょうか。

    キャンセル

  • 2020/07/04 23:17

    はい

    キャンセル

  • 2020/07/04 23:49

    ありがとうございます!

    キャンセル

-2

自分的には、StringBuilderならギリギリ理解できるかな?といった感じです。

例えば、ターミネーター(The Terminator)という映画がありましたが、ターミネーターはただ一人ではなく未来において量産化されているロボットですね。英語で-er, -orで終わる語は結構気軽に使われている気がします。

オブジェクト指向が分からない、と言ったときに、クラスの継承をあげるのではなくJavaクラスライブラリ(Javaの標準ライブラリ)のクラス名をあげているのは、センスあるなあと思いました。

オブジェクト指向には〜Manager, 〜Listenerといった、一回聞いただけじゃなんのことか分からないクラス名がたくさん出てきますがそこは慣れの問題、といったところだと思います。オブジェクト指向でないライブラリ、例えばC標準ライブラリやWin32 API(Windows API)を参照すると頭を抱えると思います。結局のところ使う分に関しては学習曲線はあまりかわらないと思うのですが…

オブジェクト指向で注目すべきは、継承やインターフェース(この書き方はよくされるのだが、スーパークラスとインターフェース、または継承と実装、というのが正しいのだろう)による「内部コード」の効率化と外側から見たときのAPIの秩序が明確化するといったところでしょうか。

クラスベースのAPIが関数ベースのAPIに比べてコンパイルも実行ももっさりしているように思えるのだろうけど、それでもクラスベースのAPIはAPIの秩序が整っているので楽といえば楽ですね。あるクラスを知っていればその兄弟のクラスの振る舞いについても感覚で分かってしまう感じ、そして関数ベースのAPIだと一つ一つ手作りなので「欲しい機能がない」ということが頻発します。開発者も利用者もAPIの全容を把握していないので起こることなのですが、クラスベースのAPIだとAPIのインターフェース(Javaのインターフェースと紛らわしい)が半自動化されているので「欲しい機能がない」という悩みが少ないと思います。その代わりもっさりしているんですけどね…。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/05 00:02

    回答ありがとうございます。
    クラスごとに管理することにより、内部コードと外部コードの両方にメリットがあると実感しました。

    キャンセル

-9

インスタンスやクラスがないオブジェクト指向のプログラム言語があります。なので、オブジェクト指向が、なんなのかを知ることとと、Java を知ることは異なります。

オブジェクト指向を理解していれば、 Ruby や Python は理解できるが、 Java のオブジェクト指向の実装を理解しても、JavaScript は全く理解できないと思います。 

質問に答えると、 インスタンスを作るという実装をしているから、インスタンスを作っている。
(もう少し突っ込むと、クラスという実装をしているから、インスタンスが必要になってくるのですが。)

インスタンスを作らずStaticメソッドだけでいいのではと思ってしまいます。 

そのとおりです。そのようなプログラム言語はあります。

特定のプログラム言語を用いない、オブジェクト指向プログラミングの書籍があればよいのですが…。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/13 15:37 編集

    どういたしまして。次回から気をつけてください。

    キャンセル

  • 2020/07/13 15:40

    大笑い
    コミュニケーション能力がないひとに、注意されたw
    能力がないひとが、自分をまもるって大変なんですね。

    キャンセル

  • 2020/07/13 15:41

    みたいですね。頑張ってください。

    キャンセル

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

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

関連した質問

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