オブジェクト指向が分からなくなってきました。
最初にオブジェクト指向を学んだとき、以下のような例がでてきました。
例)Hero(※簡単なRPGをプログラムする際の主人公を意味します)
Heroクラス :ヒーローが備えるべき性質、行動をまとめたもの(設計図)
Heroインスタンス:実際のヒーロー(人)
これは理解できました。しかし、実際に存在しないものに関してはどうしても違和感があります。
例えば以下のクラスとインスタンス。
例)StringBuilder(文字連結)
StringBuilderクラス :文字連結に必要な操作をまとめたもの
StringBuilderインスタンス:???
なぜインスタンスをつくるのかわかりません。
Heroの例にたとえると、文字連結の実際の何か???(書いていてわからない)
インスタンスを作らずStaticメソッドだけでいいのではと思ってしまいます。
なぜインスタンスを作るのか、そのインスタンスはどういう役割をしているのか、教えて頂きたいです。
追記
皆さん、回答ありがとうございます。
回答を読んでなるほどと思った反面、もう少し時間を置きたいと思いました。
というのも、いままでしっくり来ていなかったことなので、分かった気になっているだけかもしれないからです。
もう一度、自分の中で本当に理解できているのか、疑問点はないのか確かめたうえで回答およびベストアンサーを決めさせていただきます。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/04 23:07
回答7件
0
ベストアンサー
なぜインスタンスを作るのか、そのインスタンスはどういう役割をしているのか
たとえば、
java
1String hero = "ヒーロ"; 2String villain = "悪役";
というのがあったときに、hiroとvillainが異なるっていうのは、わかりますか?
当たり前じゃない
って思うでしょ?
そう、当たり前なので解説を見ないのですが、異なる変数に異なるインスタンスを作るって結構あたりまえなのです。
なんでか?っていうと変数は一時的なものが多く、どんどん変更されることが多いため
使い切りになるケースが少ないからです。
StringBuilderも文字列加工は途中の状態がいくつも続くor 続けられるように
インスタンス化して別々の文字列を加工できるように設計されています。
以下のような場合に、複数インスタンスが作れないと面倒くさそうだなというのが、わかると思います。
java
1StringBuilder heroNames = new StringBuilder(); 2StringBuilder villainNames = new StringBuilder(); 3for(story : storys) { 4 heroNames.append(story.getHero().name()); 5 villainNames.append(story.getvillain().name()); 6}
逆に状態を管理する必要がない。
または複数のインスタンスで共通にしたいものがスタティックで設計されます。
たとえば、String#join なんかは、加工するというか、ただ連結するだけですがスタティックなメソッド
なので、インスタンス化せずに利用できます。
同じクラスでも個々に状態を簡単に管理したいというのがインスタンス化したい。
という理解でよいと思います。
※既回答にありますが、インスタンス化しなくても、そのように設計/実装すれば複数の状態を管理することはできます。
投稿2020/07/04 14:50
総合スコア4826
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/04 15:12
2020/07/06 02:54
2020/07/10 13:16
0
インスタンス や static の使い道は momon-ga さんの回答で既に述べられているので省略します。
加えて、全てのメンバーに対して static をつけて作ったらどう困るか という視点で考えるのも疑問点を整理する1つの手だと思います。試しに架空の StringBuilder を作り、全てのメンバーを static にしてみましょう。
java
1public class StringBuilder{ 2 private static String value = ""; 3 public static void append(String s){ 4 value += s; //説明するために & 実装が楽なのでこうしている 5 } 6 7 public static String convertToString(){ 8 return value; 9 } 10} 11public class Main{ 12 public static void main(String[] args){ 13 //"Hello,Takashi."と出したい 14 printHello("Takashi"); // Hello,Takashi. 15 16 //"Hello,Masaru."と出したい。しかし… 17 printHello("Masaru"); // Hello,Takashi.Hello,Masaru. 18 } 19 20 public static void printHello(String name){ 21 StringBuilder.append("Hello,"); 22 StringBuilder.append(name); 23 StringBuilder.append("."); 24 System.out.println(StringBuilder.convertToString()); 25 } 26}
StringBuilder の全てのメンバーが static だった場合、こういうときに困りませんか。
他のクラスに関して同様の違和感を感じた場合も、上記と同じように もし〇〇がなかったらどう困るのか という視点で考えると同様に疑問点が整理できると思います。
疑問点は、インスタンス化しなくてもできるのに、なぜインスタンス化するのか。
先に結論を書けば、**オブジェクト指向プログラミングができないから**です。オブジェクト指向プログラミングができず、Javaという言語を利用して効率的にコードを組めないからです。
Javaは(クラスベースの)オブジェクト指向プログラミングという[プログラミングパラダイム](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%91%E3%83%A9%E3%83%80%E3%82%A4%E3%83%A0#:~:text=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%83%91%E3%83%A9%E3%83%80%E3%82%A4%E3%83%A0%20(%E8%8B%B1%3A%20programming%20paradigm,%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%91%E3%83%A9%E3%83%80%E3%82%A4%E3%83%A0%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82)を有しており、当然言語仕様もそれに合わせて作られています。クラスベースなオブジェクト指向言語において、インスタンスの生成は効率的にコードを書くために必要な手段になります。
一方、staticはJavaのMathクラスのような副作用のないメソッドを呼び出す場合においてはstaticである方が便利です。しかし、オブジェクト指向プログラミングを行う場合においては別で、staticなメソッドを呼び出す際はあらゆるオブジェクト指向の機能が使えません。例えば、継承・実装・ポリモーフィズム・カプセル化などが該当します。
オブジェクト指向を使うことのメリットは変更に対して柔軟になることですから、継承・実装・ポリモーフィズム・カプセル化を使わずにstaticで実装するとなると、めちゃくちゃなプログラムが出来上がるでしょう。
「副作用なんて悪いことばかりだし、必要ないじゃん」
「オブジェクト指向なんていらないじゃん」
と思われるかもしれません。(思わなかったらスルーしてください)
確かにその考えもその通りです。
しかし、先述したようにJavaのプログラミングパラダイムがそのようになっていますから、Javaにおいてはオブジェクト指向を利用したコーディングをする方がstaticで対応するよりも効率的です。そうなるよう言語仕様が決まっているのです。
なので、もし kobe2018 さんが本当に「オブジェクト指向なんて抽象的で分かりづらい、全部staticで良いじゃん」と思われるようであれば、プログラミングパラダイムは1つだけではありませんから、色々な言語を触ってみると良いと思います。
(副作用があることが嫌なのであれば、関数型言語はいかがでしょう。私は興味ありますが、触ったことはありません)
投稿2020/07/04 18:13
編集2020/07/10 15:51総合スコア2663
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/06 12:04
2020/07/10 13:30 編集
2020/07/10 17:37 編集
2020/07/10 17:36 編集
2020/07/13 04:42
2020/07/13 05:49
2020/07/13 05:59 編集
2020/07/13 06:02 編集
2020/07/14 02:45 編集
0
例)StringBuilder(文字連結)
StringBuilderクラス :文字連結に必要な操作をまとめたもの
StringBuilderインスタンス:???
例えるなら「文字連結業」という職業がクラスで、その技術を身に付けたひとが「文字連結屋さん」というインスタンスです。クラスに書かれたソースコードが「文字連結業」を営むに当たって必要な作業が書かれたマニュアルです。
自分が具体的な手順を知らなくても彼または彼女に頼めば作業を行って結果を返してくれます。
必要なのは頼み方の手順を覚えることだけです。
その代わり「文字連結屋さん」は少なくとも文字連結業として期待される作業は実行できるようになっている必要があります。
行うべき作業を全部自分ひとりで行うのではなく、詳細を知る別のひとに作業を頼むことによって自分がやる作業の詳細を他人任せにすることが出来るようになります。
例え話から話を戻すと、クラス分割して必要な手続きの詳細をクラス内のソースコードに隠すことにして、必要に応じて呼び出し手続きを行うことが出来るようにすれば、その分呼び出し側の負担が減ることになります。
(ただしそうなるためには適切なクラス設計がされているのが前提です。)
投稿2020/07/04 15:17
編集2020/07/04 15:19総合スコア1248
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/06 12:09
2020/07/10 13:36
2020/07/10 16:09
0
インスタンスやクラスがないオブジェクト指向のプログラム言語があります。なので、オブジェクト指向が、なんなのかを知ることとと、Java を知ることは異なります。
オブジェクト指向を理解していれば、 Ruby や Python は理解できるが、 Java のオブジェクト指向の実装を理解しても、JavaScript は全く理解できないと思います。
質問に答えると、 インスタンスを作るという実装をしているから、インスタンスを作っている。
(もう少し突っ込むと、クラスという実装をしているから、インスタンスが必要になってくるのですが。)
インスタンスを作らずStaticメソッドだけでいいのではと思ってしまいます。
そのとおりです。そのようなプログラム言語はあります。
特定のプログラム言語を用いない、オブジェクト指向プログラミングの書籍があればよいのですが…。
投稿2020/07/09 03:33
総合スコア129
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/09 03:40
2020/07/09 04:10
2020/07/09 04:15
2020/07/09 04:31
2020/07/09 04:36
2020/07/09 04:47 編集
2020/07/09 04:58
2020/07/10 02:10
2020/07/10 02:17
2020/07/10 09:59
2020/07/10 10:24
2020/07/10 10:57
2020/07/10 11:09 編集
2020/07/10 11:08
2020/07/10 11:10
2020/07/10 11:14
2020/07/10 11:19
2020/07/10 11:20
2020/07/10 11:21
2020/07/10 11:25 編集
2020/07/10 11:31 編集
2020/07/10 11:26
2020/07/10 11:27
2020/07/10 11:30
2020/07/10 11:38
2020/07/10 11:39
2020/07/10 11:42
2020/07/10 11:50
2020/07/10 11:50
2020/07/10 11:52
2020/07/10 12:13
2020/07/10 12:29
2020/07/10 12:36
2020/07/10 12:49
2020/07/10 13:40
2020/07/10 13:59
2020/07/10 14:15 編集
2020/07/11 01:38
2020/07/13 04:50
2020/07/13 04:55
2020/07/13 05:17
2020/07/13 05:19
2020/07/13 05:22
2020/07/13 05:25
2020/07/13 05:29
2020/07/13 05:33 編集
2020/07/13 05:32
2020/07/13 05:36
2020/07/13 05:37
2020/07/13 05:38
2020/07/13 05:42
2020/07/13 05:45 編集
2020/07/13 05:45 編集
2020/07/13 05:46
2020/07/13 05:48
2020/07/13 05:49
2020/07/13 05:50
2020/07/13 05:51
2020/07/13 06:36
2020/07/13 06:37 編集
2020/07/13 06:40
2020/07/13 06:41
0
自分的には、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/04 14:23
総合スコア667
0
「ある数値のリストがあって、奇数と偶数に分けてそれぞれ文字列化して連結しなさい」
StringBuilderが同時に一つしか存在できないと困りますね。
(無理やりひねり出した例なんで普通に+
で連結したり、偶数と奇数のリスト2つに分けてから連結したりで回避できますけれども。)
投稿2020/07/04 13:48
総合スコア13553
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。