カレーなる辛口Javaな転職日記 7/21 より。
この記者OOPわかってねぇ!(゚Д゚)クワッ!!ってのは同じ意見なので
突っ込み観点を違うところでもってみますた。
プログラムコードと言ってることの差分を検証したいとおもいます。


第2回 オブジェクト指向、本当に分かってる?
さすが記事。お題が挑戦的です。

オブジェクト指向とは

この手の記事、本はすべからくこの文言から入ってきます。
が、真っ当なことを語り始めるものはほとんどみかけません。
今回はどうでしょう。わくわく。

オブジェクト指向の解説に入る前に、前回実行したプログラムの意味を確認しておきたいと思います。

画像で説明が入れてあります。
前回の記事見たらソースダウンロードできたのでしてみますた。
ほんまに8行しかねぇw
コメントが3行、ロジックが3行、閉じカッコが2行という構成。

[ソースを見てみる]

この程度でOOPを語ろうとするとはなかなか豪胆なやつです。
突込みどころは3行あります。*1
まず2行目

class User1{

(,,゚Д゚)<クラス名いきなり連番かよ!

ここでは「User1(利用者1)というプログラムを定義している」と考えていただければ結構です。

(,,゚Д゚)<利用者1って2人に増えたらクラスも増えるのか!
     クラス定義で利用者数を分けるのはOOPのメリットを全く利用してないぞ!!
100歩譲っても、プログラム的にはせめてこーなっときなはれ。
  Users user01 = new Users();  // ユーザのAさん
  Users user02 = new Users();  // ユーザのBさん

初心者相手に安易なネーミングを教えると後々までに響きます。
また、安易なネーミングが役に立つことは全くないです。
簡易と安易は別物扱いするのです。


次4行目。

public static void main(String[] args){

OOPで作るプログラムの中で。
(,,゚Д゚)<main使うクラスなんざどれほどあるんじゃヴォケ!!
それよりなにより。
(,,゚Д゚)<やっぱりmainしかねぇ!!!
mainのあるクラスで自身のインスタンス作成したくないのか、
よくわからなくなるのか知らないけれど、
mainだけの例題用ソースが目につくおいらがいてます。

4行目の「public static void main(String[] args)」は「mainメソッドの宣言」です。
「メソッド」とはJavaの処理命令の1つのまとまりを示す単位で、
特に「main」というメソッドは「処理を開始する」役割を果たします。

必要でないとは言いませんが、
mainなんざおまじないと一緒だと言い切れば、
この8行中「メソッド」と呼ばれるものは一切ありません。
少なくとも「メソッド」という単語を「main」に刷り込むようなソース構成だなこれ。*2


次6行目。

Vending drink = new Vending("Coffee", 130);

(,,゚Д゚)<変数名に意味ねぇ!
(,,゚Д゚)<コンストラクタでなに全部きめとんねん!!
(,,゚Д゚)<マジックワードマジックナンバーのおまけつきだ!!!
(,,゚Д゚)<そもそもこの処理何がしたいねん

オブジェクト生成した後にやるべきことが見えません。
例題つくるためだけのコード。
もー「Vending」ってクラス名がどーでもよく思えてきそうです。
そういやこのソースが気になったので、前回記事から落としてみました。
(,,゚Д゚)<ひでぇ!!
業務中にこんなんみかけたらヌッ頃すところです。
なんかあれです。突込みどころしかないです。

//自動販売機(Vending)クラス
class Vending{

  //自動販売機(Vending)が扱う属性
  String goods;  //商品
  int price;   //価格
  int payment;  //支払
  
  //初期設定機能(コンストラクタ)
  Vending(String g, int p){
    goods = g;
    price = p;
    System.out.println("Vending was constructed !");
    System.out.println(" Goods: "+ goods);
    System.out.println(" Price: "+ price +" yen");
  }
  //支払設定機能
  void setPayment(int p){
    payment = p;
    System.out.println(payment +" yen was received.");
  }
  //商品取得機能
  String getGoods(){
    return goods;
  }
  //おつり取得機能
  int getChange(){
    return payment - price;
  }
}

(,,゚Д゚)<1文字変数使うな
(,,゚Д゚)<System.outはこのクラスの取得結果から行え。
っというぱっと見た目のことから始まり。
(,,゚Д゚)<コンストラクタでこのクラスでつかう重要データ定義すんな
     「goods」の設定常に1個やん。増加もできなきゃ変更も出来ない。
     1種類しか商品の無い自販機かこれ。
(,,゚Д゚)<「getGoods()」あるのに「getPrice()」は無いのな。
(,,゚Д゚)<おつりがマイナスになる結果をそのまま返す自販機ってどうよ?
ってな現在のソース構成から見て取れることがあり、結論。
(#゚Д゚)<これでOOP語れるものか!


先のUser1のmainの中のソースを踏まえると、
商品取得やおつりの取得ソースはこうなるよね。

drink.getGoods();
drink.getChange();

飲み物から商品やおつりが出てきそうなソースになりそうです。

[その上で記事の内容を語る]

言葉数が多くなってしまいました。
あかるくポップに行きましょう。

 6行目の「Vending drink = new Vending("Coffee", 130);」がmainメソッドの具体的な処理内容です。実行時に処理される部分ですね。

( ^ω^)<その通りですね

この行の意味は、「User1(利用者1)がVending(自動販売機)クラスから、
新しく商品名"Coffee"・価格130を設定したVendingオブジェクトを作成している」ということになります。

( ^ω^)<商品を買う前に決めた前提の設定じゃないでしょうか
      コーヒーしか売らない自販機。キャー

こうしてみると、VendingクラスはまるでVendingオブジェクトを作るための設計図であるかのように見えないでしょうか。実はそのとおりなのです。

m9(^Д^)<・・・・・・

「Vending drink = new Vending("Coffee", 130);」の1行は、
オブジェクト指向にのっとってプログラミングされている最も基礎的かつ典型的な部分になります。

m9(^Д^)プギャー!!
コンストラクタはどっちかってゆーとおまけ機能みたいなもんです。
主役はメソッド。
主役から目を背けて脇役にスポット当てて、基礎的かつ典型的とのたまうのはおかしいっしょ。
コンストラクタでなくて「addGoods()」かなにかのメソッドならワカランでもない。
drink.addGoods("Coffee", 130);
なんか変数名変だw

定義などというと構えてしまいますが、
よくよく考えてみるとオブジェクト指向とはごく当たり前の考え方なのです。

( ^ω^)<物事の捉え方だと思いますよ

図2 自動販売機オブジェクトの性質
図3 目的に従って性質を洗い出し、設計図を作成する
図4 初期設定が必要な項目と必要でない項目

( ^ω^)<その図は正しいと思いますよ。
この性質から出来上がった先ほどのソースとはまるで別モンですが。

●オブジェクトが出来上がったときに決まっていなければいけない属性値(初期値)がある
  例:商品名、価格
(中略)
つまり初期設定が必要な項目なので具体的な値を設定することになります。
例えば商品名はコーヒー、価格は130円といった値になります。

( ^ω^)<商品を1種類しか設定出来ない自販機。非現実的。

オブジェクト指向のメリット
属性と操作が一体化して無駄なく振る舞うよう、対象のオブジェクトを整理します。

(;^ω^)<属性と操作が一体化してねぇ。

クラスを作成しておくことによって、保守性も向上します。

( ゚Д゚)<こんなクラスで保守性向上するか!!

クラスを作成しておく最大のメリットは、再利用性(汎用性)です。

(#゚Д゚)<例題ソースにゃ全くねぇだろ!!!


あ。いかんいかん。

つまり、このクラスからは「ジュースの自動販売機」や「タバコの自動販売機」など、「自動販売機」と名の付くものなら何でも生成できる可能性があるのです。

( ^ω^)<何でも1種類しか定義できませんが。

オブジェクトの共通点を見いだして、その共通項目を定義した抽象的なクラスこそ、汎用性が高く使い回しの利くものになるのです。

( ^ω^)<Abstractクラスが汎用が高いかというと限定的に高いとしか答えられませんよ。
      モデリングと実際のプログラミングの差ってやつかもしれません。
      ちなみに、汎用性が高いもの、専門的な要素の強いもの、
      データの入れ物など、用途に応じたクラスの形があり、
      使用目的を明確にしておくほうが使いまわしが利くものです。

Javaの言語仕様は、オブジェクト指向に完全にマッチしたもので、
プログラミングと切り離して分析したクラスを表現することが可能です。

( ^ω^)<考え方とプログラミングがこれだけ乖離している理由がわかりますた。

Vendingクラス10行目の「Vending(String g, int p)」は
(中略)
11行目、12行目で「g」は属性の「goods」に、「p」は属性の「price」に設定する処理が書かれています。

ここでソース解説されてたよ!
( ^ω^)<コンストラクタの引数で決定するから1種類。

最終回である次回で見ていきたいと思います。

(・∀・)<続きがあるみたい!

[まとめ]

言ってる言葉とソースコードの違いが大きいことから、
言いたいことがとっても伝わらない。
OOPはこれだからわかりにくい」って言われる要因を増長しているように見える。


実際にソース動かしてみて、
「動いたわーい」
ってところから、ほな拡張してみよ〜と自己学習意識をもったところで
このソースはなんにも拡張できない。
作り直しになる。
これではOOPを利用できちゃいねぇってことになる。


学習を目的とするならサンプルコードはだいぶ重要。
それを真似することからはじまるから。
ゴミのようなコードを真似て覚えたものは
当面ロクでもないコードを生み続ける似非技術者でしかない。
って思ったおいらがいてました。

[最後に]

ちょいと文句が多くなったので。
それほど言うならおまいのソースはどーなのよって
言われた時用の、さらりとした例題用ソースをつくってみますた。
ソース一式
とりあえず動くソースなので、記述体裁のこまやかなところはまだまだなところはあるので予め。
おいらもちょっとだけサボりました。

*1:そういやこーゆーソース。やっぱりこの手の本でよくみかけるな。今改めて見直すと害悪以外のなにものでもないと思えたね。まったり。

*2:教科書みながらやったときに思ったこと。「クラスってmainがないと動かないの!?」っという勘違いを頭から追い出すのにちょいと無駄な時間を費やした記憶があるおいらがいてますた。