- オブジェクト指向なんて今すぐやめてください
196 :193[sage]:2014/04/05(土) 00:57:21.05 ID:UcRTpVkm - >>195
そのとおりだね、その問題は確かに存在する そして、それは具象クラス継承と抽象クラス継承の両者に共通する問題だから、 以降の議論では除外できると思う さて、問題は他にもあるけど、わかるかな? >>all # ....などと質問を投げて、自分は寝るとします
|
- オブジェクト指向なんて今すぐやめてください
202 :193[sage]:2014/04/05(土) 14:09:45.24 ID:UcRTpVkm - >>200
おかしいのなら、それを単刀直入かつ具体的に指摘し、 もし可能なら対策も具体的に示すべき KAC氏ならできるよね? >>198 昨晩は眠かっただけで、続きの準備はできているよ 書こうと思ったけど、しばらくKAC氏のレスを待つつもりだ
|
- スレ立てるまでもない質問はここで 135匹目
107 :デフォルトの名無しさん[sage]:2014/04/05(土) 15:40:44.80 ID:UcRTpVkm - >>102
たとえばPostgreSQLのように配列型をサポートするDBなら、それを使えばいい もしSQLiteのように基本的なデータ型しかサポートしていないDBを使っているなら、 文字列型にエンコードしてから保存するのが普通じゃないかと思う char bools[booleanの数]; for (int i = 0; i < booleanの数; i++) bools[i] = boolean[i] ? "1" : "0"; /* 真なら "1"、偽なら "0" とエンコード */ bools[i] = '¥0'; /* 文字列の終端(文字化けしてるかも....) */ もちろん取り出しでは、保存した文字列値をbooleanへデコードするコードも、別途、必要になる
|
- オブジェクト指向なんて今すぐやめてください
204 :193[sage]:2014/04/05(土) 16:23:36.51 ID:UcRTpVkm - >>203
だから、「まとも」とか「自然な」みたいな 曖昧な理想論や精神論しかKAC氏は書けないの? もしそれだけ大口を叩けるなら、「正方形とはこういうものです」という 自然な派生クラスについて、お手本となる仕様定義やコードを示せばいい KAC氏ならできるだろ? あと、何か勘違いしているかもしれないけど、 この例は「具象クラス継承の問題」を説明するために選んでいる だから、厳密で実用的な幾何学図形クラスの仕様としては不完全だよ それとも、そんな枝葉の些細な問題を大きく取り上げたいのかな?
|
- オブジェクト指向なんて今すぐやめてください
206 :193[sage]:2014/04/05(土) 16:46:03.46 ID:UcRTpVkm - >>205
だから、「クラス設計が酷い」のなら、それを具体的に指摘するか、 きれいなクラス設計を示しなさい、という話だよ ただ単に「まともでない」「不自然だ」「酷い」と吐くだけなら幼児にもできる 大人ならば、ナゼそうなのかという論理的な理由を明解に文章化できるはず
|
- オブジェクト指向なんて今すぐやめてください
210 :193[sage]:2014/04/05(土) 18:08:44.01 ID:UcRTpVkm - では、>>194の具象クラス設計について、3つの問題点を以下に示す
(1) Squareクラスは常に2つの属性を持つが、正方形の高さと幅は 必ず等しいから情報量として無駄であり、どちらか1つがあればいい (2) Squareクラスではsetterメソッド Square#height= と Square#height= が 公開されているから、インスタンス化した後にこれらのメソッドを使うことで 高さと幅の異なる正方形を作成できてしまう (3) 正方形の周辺の長さは大きさを4倍するという簡単な計算で求めることができるのに、 この実装コードでは計算量として複雑になる これら具象クラス継承固有の問題は、「抽象クラス-具象クラス」という概念を 導入することによって解決できる (長過ぎるので、ここで切る)
|
- オブジェクト指向なんて今すぐやめてください
211 :193[sage]:2014/04/05(土) 18:09:22.83 ID:UcRTpVkm - (>>210の続き)
class SubclassResponsibility < StandardError; end # 例外クラス(StandardErrorはRubyの標準クラス) class AbstractRectangle # 長方形クラス(抽象クラス) def area; raise SubclassResponsibility; end # 面積を計算する(抽象メソッド) def perimeter; raise SubclassResponsibility; end # 周辺の長さを計算する(抽象メソッド) end class Rectangle < AbstractRectangle # 長方形クラス(具象クラス) attr_accessor :height, :width # 高さと幅 -- getterとsetterを伴う属性 def initialize(height, width) # コンストラクタ @height = height; @width = width end def area; @height * @width; end # 面積を計算する def perimeter; (@height + @width) * 2; end # 周辺の長さを計算する end class Square < AbstractRectangle # 正方形クラス(具象クラス) attr_accessor :size # 大きさ -- getterとsetterを伴う属性 def initialize(size) # コンストラクタ super(); @size = size end def area; @size * 2; end # 面積を計算する def perimeter; @height * 4; end # 周辺の長さを計算する end 最後に、これらを比較した(集合の)ベン図とクラス図を以下のリンク先で示す http://www.h6.dion.ne.jp/~machan/misc/abstract-class.png
|
- オブジェクト指向なんて今すぐやめてください
214 :193[sage]:2014/04/05(土) 18:43:44.47 ID:UcRTpVkm - >>208
>もしかして193のいう図形ってのはたとえば以下のような特徴を持つのか? > > 正方形は大きさを変化させることができるが長方形は変化しない。 いいや持たないよ、長方形は高さと幅を(setterメソッドで)変化させることができる 変化させることができるから、「attr_accessor :height, :width」というコードへ コメント「# 高さと幅 -- getterとsetterを伴う属性」を書いている (なお、Rubyではreader/writer/accessorという用語を使うのが一般的であるが、 Rubyに不慣れな人も多いことを考慮し、getter/setterというJava用語で記述した) それともgetter/setterという用語すら知らなかったのかな? もしもLAC氏が「Rubyはまったく知らない」のなら、最初にそれをレスすべきだよ それなら(自分はJavaが不慣れだから)時間はかかるけど、Javaへ書き直すこともできた KAC氏のいつものパターンだけど、 後になってから「言い訳することばかり考える」のは、いいかげん見苦しい
|
- オブジェクト指向なんて今すぐやめてください
215 :193[sage]:2014/04/05(土) 18:46:53.76 ID:UcRTpVkm - >>213
それはコーディングのバグだね 以下のように訂正する X: def area; @size * 2; end # 面積を計算する O: def area; @size * @size; end # 面積を計算する
|
- オブジェクト指向なんて今すぐやめてください
216 :193[sage]:2014/04/05(土) 19:08:38.75 ID:UcRTpVkm - >>207
>親クラスのインスタンスの代わりに子クラスのインスタンス入れても動かない例。 そのとおりだね、まさに「よくある例」のハズだと思うんだけど、 なぜそれにKAC氏は気付かない or 気付けなかったんだろうか.... >あと気軽に多角形でクラス階層育てようとして、 >案外うまくいかねーな、おいしくないな、ってのもよくある話。 その話もよくあるけど、こちらは抽象クラス継承でも解決できない問題だ オブジェクト指向分析/設計(OOA/OOD)とオブジェクト指向プログラミング(OOP)との違いの 一つとも言える、より本質的な問題と言える この問題については、このスレでも以前に一部書いた(>>71)けど、 機会があれば議論を続けたいと思う (今は、具象クラス継承の問題とごっちゃにすべきじゃないから....)
|
- オブジェクト指向なんて今すぐやめてください
224 :193[sage]:2014/04/05(土) 20:58:20.10 ID:UcRTpVkm - >>218
設計がおかしいのなら、具象クラス継承のまま問題を解決できる 「正方形クラスを継承して長方形クラスを定義」したコードを示せばいい (Rubyでなくても、C++/Java/C#/Smalltalkくらいなら読むことはできるよ) それが示すことが「具象クラス継承でも問題無し」実証することになる 論よりコードだ >>21 >あまりにもツッコミどころが多すぎて書かなかっただけ。 また後から言い訳をするのかな? コーディングのミス(=バグ)は、コードを修正すればいい でも具象クラス継承という設計のミスは、設計にたちかえって対策しなさい、という話だ >>218へのレスと同様、「実装あの仕方が下手なだけ」なら、 具象クラス継承のまま問題を解決できる「上手な実装」を示せばいい
|
- オブジェクト指向なんて今すぐやめてください
233 :193[sage]:2014/04/05(土) 21:42:52.00 ID:UcRTpVkm - >>220
>(2)について、.....(中略).... >>>194においてwidthとheightをprivateにしていい。 たとえばRubyならば、>>194のコードのSquareクラス定義内に 「private :height, :width」という宣言を追加すれば実現できるかもしれない でも、今回はたまたま直接の継承関係にあるからprivateにするという対策に 気付くことができるけど、多段継承で多数の属性を持つ現実のクラスライブラリ開発では、 どの属性がpublicのままでどれがprivateにすべきか洗い出すのは労力が多すぎる それなら最初から抽象クラス継承で再設計するほうが、全体としては楽になると思う >(3)は、適切な計算式を使うようにオーバーライドすれば良い 適切な計算式とは、「@height * 4」あるいは「@width * 4」になると思うけど、 それは高さまたは幅の「どちらかを選ぶべきか」という悩ましい問題を抱えることになるよね とはいえ、この反論がいささか苦しいのは認める >問題があるとすれば(1)だけ。 まず根本に(1)の問題があり、(1)によって(2), (3)の問題が派生しているという意味で、 この部分の指摘はまったく正しいと思う
|
- オブジェクト指向なんて今すぐやめてください
234 :193[sage]:2014/04/05(土) 21:52:36.59 ID:UcRTpVkm - >>221
"中に入れて" という意味が分からない 実際、>>194では、メソッドSquare#set_size(size)の定義の中で setterメソッド Rectangle#=(height) と Rectangle#=(width) を使って実装している Smalltalkでもかまわないんで、"中に入れて" をコードで表現してくれないかな?
|
- オブジェクト指向なんて今すぐやめてください
235 :193[sage]:2014/04/05(土) 21:53:55.81 ID:UcRTpVkm - >>222
>お前のソースは酷すぎて意図すらロクに相手に伝わらない事を自覚しろ・・・ setter/getter というキーワードを見落とすKAC氏に言われてもね....
|
- オブジェクト指向なんて今すぐやめてください
240 :193[sage]:2014/04/05(土) 22:18:54.40 ID:UcRTpVkm - >>225
いや、こちらはコードを書いたのだから、次はKAC氏がコードを示す番だろ 最初に「Rubyをまったく知らない」のに「知ったかぶり」をしたのだから、それを突き通せ (もし次にコードを示すターンがあれば、その時は自分が書くよ) それとも、KAC氏とは大口を叩いたあげく、いざとなるとコードが書けない「口先番長」なのかな? もちろん>>224で書いたように、C++でもかまわないよ では、継承関係を持つ2つの具象クラス:長方形(Rectangle)」と正方形(Square)に限定し、 >>210で挙げたものと類似の問題が生じない実装をコードで示してくれ 待っているよ
|
- オブジェクト指向なんて今すぐやめてください
241 :193[sage]:2014/04/05(土) 22:25:27.15 ID:UcRTpVkm - >>227
>どうせ後で「後出し」とか言い出すんだろうから先に言っといてやるけど、 いや残念ながら、その問題はすでに>>195氏が指摘していて、それに対して>>196でレスを返している 頭に血が上っているみたいだけど、もう少し冷静になった方がいいと思う >ソース見て判断したら読みづらいし、 読みづらいも何も、LAC氏は「Rubyをまったく知らなかった」んじゃないの? >ソース見て判断したら読みづらいし、 捨て台詞ですか?
|
- オブジェクト指向なんて今すぐやめてください
242 :193[sage]:2014/04/05(土) 22:35:36.39 ID:UcRTpVkm - >>241の最後の一文を訂正
誤: >>ソース見て判断したら読みづらいし、 > >捨て台詞ですか? 正: >>今回はお前の実装指摘するくらいはしといてやるよ。 > >捨て台詞ですか? こちらも冷静さを失っているようだ 注意しよう
|
- オブジェクト指向なんて今すぐやめてください
243 :193[sage]:2014/04/05(土) 22:45:52.66 ID:UcRTpVkm - >>231
>>241で書いたように、次はKAC氏がコードを示す番だ では、それら意図を満たし、なおかつ>>241の条件: 継承関係を持つ2つの具象クラス:長方形(Rectangle)」と正方形(Square)に限定し、 >>210で挙げたものと類似の問題が生じない実装 をコードで示してくれ では、待っているよ
|
- オブジェクト指向なんて今すぐやめてください
248 :193[sage]:2014/04/05(土) 23:41:03.68 ID:UcRTpVkm - >>246
コードが汚いとか仕様が意味不明と騒いでいるのは KAC氏一人だけじゃないのかな? それ以外の具体的な指摘には、その各論が正しければ正しいと認め、 違っていれば真面目に答えているつもりだ 実際、>>213のバグ指摘はそれを素直に認めて訂正してる もし>>194の仕様では満足できないなら、KAC氏が自ら幾何学図形クラスの 仕様について、お手本となる定義を示せばいいと思うがね
|
- オブジェクト指向なんて今すぐやめてください
249 :193[sage]:2014/04/05(土) 23:41:52.81 ID:UcRTpVkm - >>240,243ではKAC氏のコードを待っていると書いたけど、
やっぱり、こちらでもC++のコードを示すことにする ただし、>>194に対して直接LAC氏がC++のコードを希望したと想定し、 >>194のRubyコードの意味を変えずC++へ移植したものとする また、そのほうが両方のコードを比較できるから、 KAC氏以外の人達にとっても有益だと判断する (ただし、>>213,215のKAC氏指摘バグは、最初から対策済みとする) まず最初は、具象クラス継承のC++版コードを示す class Rectangle { public: Rectangle(int h, int w): height(h), width(w) void set_height(int h) { height = h; } void set_width(int w) { width = w; } virtual int area(void) { return height * width; } virtual int perimeter(void) { return (height + width) * 2; } private: int height, width; } class Square: public Rectangle { public: Square(int s): Rectangle:(s, s) {} void set_size(int s) { set_height(s); set_width(w); } } // 使用例 Rectangle R(3, 5); Square(7); (続く)
|
- オブジェクト指向なんて今すぐやめてください
250 :193[sage]:2014/04/05(土) 23:55:53.07 ID:UcRTpVkm - (>>249の続き)
次は、>>211のRubyコードに対応した抽象クラス継承のC++版コードを示す class AbstractRectangle { public: virtual int area(void) = 0; virtual int perimeter(void) = 0; virtual ~AbstractRectangle() = 0; }: class Rectangle: public AbstractRectangle { public: Rectangle(int h, int w): height(h), width(w) {} void set_height(int h) { height = h; } void set_width(int w) { width = w; } virtual int area(void) { return height * width; } virtual int perimeter(void) { return (height + width) * 2; } private: int height, width; }; class Square: public AbstractRectangle { public: Square(int s): side(s) {} void set_size(int s) { side = s; } virtual int area(void) { return size * size; } virtual int perimeter(void) { return size * 4; } private: int size; }; (終わり)
|