アプリ版:「スタンプのみでお礼する」機能のリリースについて

クラスという概念がいまいちわかりません。
例えばMathクラスにはmax,sin,cos,tanなどの関数がありますが、
ようはクラスって関数(メソッド)を集めたものと思います。
そのような理解であっておりますでしょうか?
であるならば、わざわざクラスに分類しなくても、関数(メソッド)で良い様に思うのです。
何でわざわざnew演算子を使ってオブジェクトを作成してからでないと
関数が使えないようにしたのか、さっぱりわかりません。
関数でいいじゃないですか。と思うのです。
「キミはsin()関数を作ってね、キミはcos()関数を作ってね。」

「キミはMathクラスのsinメソッドを作ってね、キミはMathクラスのcosメソッド作ってね」
では意味的にはたいして違わないと思うのです。
よろしくお願いします。

A 回答 (5件)

Mathクラスは似たような関数を集めて纏めただけの、


ライブラリクラスなので厳密にはクラスとは呼べないです。
よって、このクラスを挙げてオブジェクト指向プログラミングと
構造化プログラミングの違いは何?と聞かれても、
「違わない」と答えます。

構造化プログラミングとオブジェクト指向プログラミングの違い
○構造化プログラミング
まず手続きありきなので、処理とデータの間に関連が無い。
例:仕様上正弦値を計算する必要があるならば、
sin()関数を呼び出してデータを渡し結果を得る。
しかし、sin()はデータと関連が無いためかならず数値が渡されるとは限らないし、
数値側(データ側)から見れば、正弦値を計算する関数がどれか知らない。
よって、プログラマがデータと手続きを正しく組み合わせる(出会わせる)必要がある。(裏を返せば、あり得ない組み合わせも出来てしまう。)

○オブジェクト指向プログラミング
まずデータありきで、このデータに対してどのような手続きが必要であるか(つまり、正しいデータと手続きの組み合わせを保障する)必要で無いか(該当データにそぐわない手続きは処理させない。つまりあり得ない組み合わせを排除する)をクラスという構造を使用して関連付けている

オブジェクト指向プログラミングを勉強しているならは、
もっと、データと手続きが密接に関連したものを参考にすべきです。
たとえば「車」クラスなど。
「車」クラスには「前進()」「停止()」「右折()」「左折()」等の手続き(メソッド)が考えられます。
「車クラス」は「車」というデータの振る舞いがメソッドによって明確になっていて、それ以外のことは出来ない。(例:車.飛行()は無い。つまりあり得ない組み合わせは出来ない)

これを構造化プログラミングで表現すると、
「前進()」「停止()」「右折()」「左折()」「飛行()」の5つの関数と「車」というデータがばらばらに存在することになります。
しかし、関数とデータがまったく関連付けられていないため、
「車」データは自身にどんな振る舞いが許されるのかまったくしりません。
よって、飛行()関数に対して「車」データを渡せてしまうし、
「前進()」に対して「椅子」データを渡せてしまいます。※1

「車」という例題は簡単すぎるため、※1のようなミスはあり得ないとは思いますが、
ここであなたが構造化プログラミングをしていて、
あなたの目の前に初めて見るデータがあったら、このデータに正しく関数を関連付けられるでしょうか?
もし、クラスによって既に関連付けられていたら間違えることもないし、楽だと思いませんか?

構造化プログラミングをドンドン極めていくと、
最終的に出来る限り最小限の労働力でプログラミングしようと言うところに行き着きます。
具体的には、「再利用性を高める」とか「可読性を高める」とか「バグ(使う関数を間違える等。※1のこと)を減らす」等。
そして、いつの間にかそれを実現するために、
構造化プログラミング内でクラスもどきを作るようになっていくと思います。

オブジェクト指向プログラミングとは、先人達がこういった苦労を重ねないように、
無駄を省いていった結果生まれたものだとおもいます。

このようになぜオブジェクト指向が必要となったのかという角度からも考えると、なぜクラスなのかということも理解しやすいかと思います。
    • good
    • 0

他の方がおっしゃているようにMathクラスはユーティリティクラスですので、クラスの概念を説明するときには不向きですね。


でもまず誤解が無いようにMathクラスを説明しますと、Mathクラスのメソッドは全てstaticメソッドですので、Mathクラスはオブジェクトを生成して使用しません。

Math.sin(45)

というようにMathクラスのsinメソッドを使用しますよとなります。
つまり、Mathクラスは計算に関するメソッドを集めたにすぎません。(コンストラクタもない(不可視な)のでオブジェクトを生成することも出来ません。)
つまり、karasu4649さんがおっしゃるように、 メソッドの寄せ集めです。しかし、これはMathクラス等のユーティリティクラスに限ったことであり、クラスの本質は少し違います。

クラスは、一連のカテゴリーに分けられるデータ(メンバ)と操作(メソッド)の寄せ集めです。要は雛型です。
例えばここにBoxクラスがあるとします。

class Box{
private Object obj ;

public Box(){
this.obj=null;
}

public void put(Object obj){
this.obj=obj ;
}

public Object take(){
Object obj = this.obj ;
this.obj = null ;
return obj ;
}
}

上記のような定義だとします。
このBoxクラスをnewしてオブジェクトを生成することで、中身の違ったBoxクラスを複数用意することができるのです。
例えば、食べ物が入ったBoxであったり、テレビが入ったBoxだったりするわけです。
そしてここに、Delivererクラスなるものをつくります。
定義はめんどくさいので割愛しますが(笑)、DelivererはBoxを指定したところに運ぶというメソッドを持つとします。
どうでしょう?ここでまた、Delivererクラスのオブジェクトを生成して運ばせるBoxや配達先の違うDelivererが生成できますね。
そして、DelivererはBox(という型のオブジェクト)を運ぶことだけ知っていればいいので、Boxの中身(オブジェクト)はどんなものでもいいのです。

このように、関連のあるデータや操作をまとめることで、役割がはっきりし、また、膨大なサイズのプログラムになったとしても、図などにして構成を分かり易くすることが可能になります。
単なる関数の寄せ集めにしてしまうと、put(Object obj)なんてメソッドがあったら、どんな処理をするか想像しずらくないですか?他にも同じような名前の関数もできてしまいそうだし、分かり易くする為にメソッド名をやたら説明調にしなきゃいけませんよね?
しかし、Boxのput(Object obj)の場合、箱に物を詰めるのねというようなイメージがしやすいと思います。
また、Mathにいたっても関数の寄せ集めでしかありませんが、計算に関する関数しかありませんし、逆に言えば、計算に関する基本的なメソッドが一通り揃っています。何かしらの計算をする処理が必要になった場合は、Mathクラスのドキュメントを見てみようとか、他にもどこどこのクラスを見てみようというように出来るわけですね。これは、大変便利ですよ。


簡単に説明したかったのですが、思いっきり長くなってしまいましたね(笑)。
それにクラスについての説明はまだ不足してます。3大要素とも言える、カプセル化、継承、ポリモフィズムといったところがクラスの肝になってきます。
でもこれは、クラスについてもう少し学ばれてからの方が良いと思います。
    • good
    • 0
この回答へのお礼

皆様のおかげでクラスに対する理解がぼんやりと見えてきました。
関数と引数を正しく組み合わせるためのテクニックというものだと思いました。どうもありがとうございました。

お礼日時:2008/01/19 12:37

クラスってのはオブジェクト指向の中核をなす概念です。

一般には、データとそれを操作するメソッドをひとつに集めたものと考えれば良いでしょう。
オブジェクト指向の考え方を実際のコンピュータシステム上で実現しようとしているのが、オブジェクト指向言語です。

さて、Mathクラスですが、これは、特殊なクラスと考えた方が良いと思います。オブジェクト指向言語は、オブジェクト指向の考え方を実現しようとしていますが、一方で、オブジェクト指向の考え方を忠実に実現しようとすると、場合によっては、実装しにくい仕様になってしまったりします。で、そのあたりのトレードオフにより、Mathクラスのような、メソッドばかりを集めたクラスが必要になったりしたのだと思います。
    • good
    • 0

クラスって考えは、オブジェクト指向プログラミングに通じますね。


で、実際のコーディングにおいて以下のメリットがあります。

1.やりたい処理が小さな手間でコード化できる。
 ->アルゴリズムを自分で考えるのじゃあなく、コンパイラに考えてもらう。
 ->構造化プログラムなら自分で書くべきコードをコンパイラが生成する。
2.バグが少ない。
 ->人間じゃあなく、コンパイラが行う割合が増えるのでバグが減る。
3.機能拡張が簡単。
 ->拡張部分の多くのコードをコンパイラが生成。

ってことを狙っていると思っています。実際、C++の教育書籍に掲載されている、ちょっと複雑と思える例題が、短いコードで実現されているのを見て驚いたものです。
ただ、この例題はC++でしたので、Javaで同等なことができるかはわかりませんが。

こういう方針で作ったプログラムが、一見して「関数の寄せ集め」にみえることは確かだと思います。でも、その背景にあるプログラミング戦略は、構造化プログラミングの1段あるいは2段上の発想を必要としていると思います。良く「デザインパターン」なんて言葉がでてきますが、そういった知識も必要だと思います。

それから、簡単・小規模なプログラムだと、上記のようなメリットはあまり感じることが無いと思えます。複雑・大規模・変更が多いプログラムにおいて、「デザインパターン」など、いろいろな手法を使いながら、苦労して設計した無形の作業が、その後の機能変更・拡張作業が楽になることで報われるものだと思います。

「このプログラムの機能なら、構造化プログラミング手法で、もっと楽に早くできたよ」って感じるならば、それはまだクラスとかオブジェクト指向を適用する必要のないプログラムかもしれません。(でも、初期開発は大変でも、メンテナンス性はずーと良いことが多いはず)
    • good
    • 0

>ようはクラスって関数(メソッド)を集めたものと思います。


>そのような理解であっておりますでしょうか?
そうとも言える。

ポイントは闇雲に集めているわけではなく、プログラムを階層化するように「うまく」集めることが重要です。

同時に階層化することで、スコープが分かれるという利点があります。
スコープが分かれることによって名前の衝突を回避することができます。
つまり karasu4649 さんの作成したクラスにも独自に sin() 関数を実装することができます。

>関数でいいじゃないですか。と思うのです。
プログラムの規模が小さければ、コードの海に関数が浮かんでいる風でもコーディング可能です。
あたかも main 関数を持つクラスが一つしかない教科書のサンプルプログラムのように。

しかし、経験を積むとわかるように、広大なソースコードの海に大量の関数がちらばっていると、コードを読むことが急速に困難になります。

>何でわざわざnew演算子を使ってオブジェクトを作成してからでないと
>関数が使えないようにしたのか、さっぱりわかりません。
そのために static 関数があります。Math オブジェクトを作成することなく sin() 関数は利用可能です。


以上、素人の意見でした。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!