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

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

新規登録して質問してみよう
ただいま回答率
85.50%
オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

2回答

2539閲覧

プロパティを変更するメソッド

mightyMask

総合スコア143

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

0クリップ

投稿2016/12/03 08:16

オブジェクト指向についての質問です。
自身のプロパティを変更するメソッドを作るとき、このようなメソッドを作るのはオブジェクト指向な考え方ができてない外道なのでしょうか。

例えば、サイヤ人クラスがあるとします。
変身状態、戦闘力、スピードを表すプロパティを持っています。
スーパーサイヤ人に変身するメソッドを持っています。
スーパーサイヤ人になると、戦闘力は確実に上がりますが、スピードは落ちる場合があるとします。

1.返り値をvoidにして、自身のプロパティを変更する。
2.返り値をサイヤ人型にして、自身は変えず、サイヤ人になった時のインスタンスを返す。

1が正しいやり方なのでしょうが、2のような事をしたい場合もあります。

外部クラスで、サイヤ人クラスの孫悟空というオブジェクトを持っているとします。
ここで、スピードが上がるなら変身するという処理をしたいとします。

1のやり方だと、

if( 孫悟空.スピード < 孫悟空.クローン().変身(スーパーサイヤ人).スピード ) 孫悟空.変身(スーパーサイヤ人)

2のやり方だと、

if( 孫悟空.スピード < 孫悟空.変身(スーパーサイヤ人).スピード ) 孫悟空 = 孫悟空.変身(スーパーサイヤ人)

んー、やっぱり1が正しいのですかね。
どちらも良いコードとは言えない気もします。
正解はあるのでしょうか。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

【注意】下記文章には私感が入っています。


**正解はありません。**どちらも正しいです。

これはmutable(変更可能)とimmutable(変更不可)の終わりなき戦いです。

###mutable…それは命令型プログラミング

C++由来のオブジェクト指向は構造体の拡張でした。元々はデータをまとめた構造体ですので、その使い方の考え方も変わりませんでした。オブジェクトは基本的にmutableであり、メソッド(言語によってはメンバー関数とも呼ばれる)によってオブジェクト内のデータ、つまりインスタンス変数(言語によってはメンバー変数、フィールド変数とも呼ばれる)として保存されている何かを変更するというものでした。

この考え方はCの時から使われており、命令型プログラミングと言われるものです。命令型プログラミングはデータ(オブジェクト)を命令(メソッド)で随時変化されながら、計算を行う手法です。この方法はオブジェクトの生成という新たなデータ領域を確保する必要が無い等の理由により、次のような利点がありました。

  • メモリの値の書き換えのみのため、高速。
  • オブジェクトの生成がないため、GCが無い言語でもメモリ管理が不要。
  • 命令型プログラミングになれたプログラマーがオブジェクト指向に入門しやすい。
  • 現実世界の物で例えたオブジェクト指向の説明がしやすくなり、直感的。

Cを拡張したC++を始め、メジャーなオブジェクト指向言語、例えばPython、Ruby、Java、JavaScript、C#等はこの命令型プログラミングによるオブジェクト指向を取り入れました。Javaの流行やGoFによるデザインパターンなどオブジェクト指向の研究が進んでも、mutableなオブジェクトであることが前提であり、メソッドによってオブジェクトを変化させていくという考え主流でした。

しかし、この方法には欠点がありました。

  • マルチスレッド環境において、別スレッドによる変更を考慮しなければならない。スレッドセーフなオブジェクトを作るにはオブジェクトの動作定義部分、つまりそのクラスにおいてロックや同期を実装しておく必要がある。マルチプロセス、マルチノードではさらに複雑なロックや同期を考える必要がある。
  • オブジェクトの状態別にテストを行う必要があるため、ユニットテストが複雑になる。その分、テスト漏れが発生する確率も高くなる。

現代において、単体の速度より並列処理によるスケールアウトが可能かが重要視されています。マルチスレッドはもちろんのこと、マルチプロセス、マルチノードでも動作できるかは大規模システムでは重要なことです。また、テスト駆動開発等、テストはますます重要視されており、それが書きやすいか書きにくいかは重要なテーマです。そのため、命令型プログラミングだけでは限界が来つつありました。

これらを解決するために復活したのが関数型プログラミングです。

###immutable…それは関数型プログラミング

いきなり関数型プログラミングという言葉が出てきましたが、なんじゃらほいという感じでしょう。しかし、immutableなオブジェクトを語る上で関数型プログラミングという手法は避けて通れません。

関数型プログラミングの歴史は古く、Cよりも古いLISPが最初と言われています。LISPは優れた言語でしたが、メインのアプリケーションに使われることは少ない物でした。その後も、Haskell、Erlang、OCamlなど関数型プログラミングに適した関数型言語が作られますが、メジャーに立つことはありませんでした。関数型プログラミングは一時期人々に忘れ去られた存在だったのです。しかし、ひっそりと時を伺うようにその進化は続けられていました。

そして、最近になって関数型プログラミングは大きく注目を浴びるようになりました。それは、命令型プログラミングの限界を解決するのに非常に適していたからです。そう、先に挙げた二つの欠点を関数型プログラミングでは克服していたのです。それは、オブジェクトをすべてimmutableとして扱うことで、並列処理におけるロックや同期を不要とし、状態別のテストも不要にできたからです。

そう、関数型プログラミングでは、基本的に全てがimmutableなオブジェクトです。一度生成されたオブジェクトが変更されることはありません。でも、変更不可だと今までの方法が使えなくなりますよね?そこで、それを簡単に扱えるように、ラムダ式と高階関数、再帰、カリー化と部分適用、パターンマッチ、モナドなどの方法が開発され、(関数型プログラミングに慣れている人にとっては)簡単にデータを処理できるようにしたのが関数型プログラミングなのです。逆に言うと、immutableなオブジェクトとして扱うなら関数型プログラミングを使わないと難しいと言うことです。

関数型プログラミングの考え方は、技術の最先端の人達にすぐに取り入れられました。例えば、オブジェクト指向と関数型プログラミングを融合したScalaが作られました。Python、Ruby、C#など本来は命令型プログラミングのオブジェクト指向でも、関数型プログラミングがしやすくなる機能を取り入れ、(部分的に)関数型プログラミングとして書くことも可能にしました。現代において関数型プログラミングは主流技術の一つであり、全体、もしくは、部分的にでも取り入れないと安全な大規模システムは難しくなると考えられます。

もちろん欠点があります。それは命令型プログラミングの全く逆です。オブジェクト生成によるオーバーヘッド、GC必須、関数型プログラミングを知らないと難しい、などなどです。

###結局どちらがいいのか?

一長一短です。並列処理やテストに強いのはimmutableの方でしょう。より安全にプログラミングをすることができます。しかし、速度面ではmutableに劣ります。オブジェクトの生成を省略できるような最適化ができないと毎回オブジェクトを生成するコストはバカになりません。また、ファイルオブジェクトのように副作用と状態変化が前提のものはimmutableで作ること自体が不可能です(モナドを使えばできますが、ここでは説明しません)。

現代におけるオブジェクト指向はmutableとimmutable、命令型プログラミングと関数型プログラミングをいいとこ取りで組合せながら行うのが主流になってくると個人的には思っています。

投稿2016/12/03 10:53

編集2016/12/03 10:58
raccy

総合スコア21733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

自身のプロパティを変更するメソッドを作るとき、このようなメソッドを作るのはオブジェクト指向な考え方ができてない外道なのでしょうか。

そんなことは、欠片もないです。
自分自身を変更することのないオブジェクトは、そもそもオブジェクト指向ではないです。

ところで、2はオブジェクト指向的な考え方には含まれないような気もしますが、使ってはダメというのもあり得ないです。
目的に対して有用な機能をオブジェクト指向に則ってないから使わないというのはあまり利口な選択ではないと思います。

投稿2016/12/03 08:58

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問