プロが教えるわが家の防犯対策術!

staticメソッドの使いどころについて質問させてください。

まず、メソッドの内部で、そのメソッドが定義されているクラスのイ
ンスタンス変数を使用している場合は、そのメソッドはインスタンス
に依存するので、インスタンスメソッドにしかできないのはわかり
ます。疑問なのは、「じゃあこのメソッド内でインスタンス変数を使
わないで引数で渡せるように作れば、インスタンスに依存しないの
でstaticにしていいの?」(※)ということです。

さらにこうも思います。

なんとなくですが、※のようなことをしたらオブジェクト指向の意味
がない気がします。理由ははっきりわかりません。ほんとになんとなく
です。(奇跡的にあたっていたとしても、理由を教えて下さいm(_ _)m)

そして、さらに混乱するのが、ユーティリティの関数などでstaticメ
ソッドになっているのを見ました。この場合はどうしてメソッドの引
数を指定するようにしていて、クラスのインスタンス変数を使うこと
はしないのか。

以上、大変下手な文章ですが、混乱しているポイントが伝わったでし
ょうか?

よろしくお願いします。

A 回答 (4件)

回答者の皆さんが色々と回答されているようなので敢えて直接的な回答はしませんが…。



GoFのデザインパターンをご存知ですか?
「オブジェクト指向」でプログラムを組むときのデザインパターンなんですが…。
その中に「Singletonパターン」というクラスのインスタンスは1つしか生成されないというデザインパターンがあります。
下記がそのサンプルコードです。

final class Singleton {
private static final Singleton instance = new Singleton();
private Singleton(){};
public static Singleton getInstance(){
return Singleton.instance;
}
}

このデザインパターンだとstaticメソッドを使用しないとSingletonを保証できませんよね?

staticというキーワードはその必要性に応じて使用して、またその「必要性」がどのような場合なのかを理解する方が大事だと思います。
    • good
    • 0

staticでないものは、それぞれのインスタンスごとに情報を持つ。


staticなものは、クラスごとに情報を持つ。

この違いがよくわかってない気がする。どうも「staticなメソッド」だけでなく「staticなフィールド」もあることを忘れていないか。staticなメソッドは、staticなフィールドにはアクセスできる。

たとえば、あるクラスを定義するとき、それぞれのインスタンスごとに値を保持するようなものでなく、「このクラスではすべてのインスタンスで同じ値が設定される」というものもある。こうしたものはstaticなフィールド(クラスフィールド)として用意される。そして、このstaticな値だけを利用して処理を行う場合、それはstaticなメソッド(クラスメソッド)として実装される。

なぜ「staticはオブジェクト指向の意味がない」と考えるかよくわからないが、「オブジェクトごとに用意されるものと、すべてのオブジェクトで共通して用意されるもの」の両方を用意するのはオブジェクト指向でも普通のことだ。逆にないと困るだろう。

>オブジェクトで扱えることって、メモリの消費を犠牲にしてでも
>一回きりの関数と比べたとき、便利なものですよね?
>だけど逆に、オブジェクトで扱う必要がないのに、無理にオブジェクト
>として扱ってもそれは、犠牲を払った分の効果がないので、そこで
>staticという仕組みがあるのですかね?

このへんがよくわからないが、確かにクラスメソッドはインスタンスメソッドよりコストはかからない。だから、クラスメソッドですむものはわざわざインスタンスメソッドにする意味がない。これは当然。

どうも、「クラスはただの関数ライブラリみたいなもので、インスタンスを作って動かすのがオブジェクト指向だ」みたいな、変な思い込みをしている気がする。そんなあんたに、衝撃の事実を教えよう。

クラスは、「オブジェクト」なんだぜ?

プログラムを実行するとき、Java仮想マシンは、まずクラスをメモリにロードし、「クラスというオブジェクト」を作る。そして、その内容をコピーして「インスタンスというオブジェクト」を作る。どちらもオブジェクトだ。メソッドをクラスに置くか、インスタンスにおくか、それはそのメソッドの「性質」によって決められるものであって、どちらにおこうがそれは「オブジェクト」なんだ。単に、「クラス」と「インスタンス」という性質の異なるオブジェクトであるに過ぎない。

オブジェクト指向は、「すべてがオブジェクトとして存在する」ことに意味がある。そういう意味では、Javaはオブジェクト指向としては不完全(プリミティブタイプがある)だ。が、たとえばRubyなどは、整数も実数も真偽値も全部オブジェクトだ。「これはオブジェクトにする必要がないからそうじゃないものにしよう」という発想こそがオブジェクト指向的ではない。どんなものであれ、すべてオブジェクトとして存在し扱えるということが重要なんだ。

この回答への補足

>staticでないものは、それぞれのインスタンスごとに情報を持つ。
>staticなものは、クラスごとに情報を持つ。
static変数の場合は、”static”の意味が理解できるんですが、メソッドになるととたんにわからなくなります。

例えば書式変換のメソッドはなぜstaticにするのでしょうか?どうもstaticメソッドと非staticメソッドの定義の違いは理解できるのですが、その分類ができないみたいです。Java以前の問題ですかね(ToT)

>どうも、「クラスはただの関数ライブラリみたいなもので、インス
>タンスを作って動かすのがオブジェクト指向だ」みたいな、変な思
>い込みをしている気がする。
ご指摘の通りです。クラスは設計図だから、オブジェクトはそれから作るインスタンスのことだと思っていました。オブジェクトとインスタンスって同じ意味なはずなのになんで言い方が二つあるんだろうと思ってました。

>単に、「クラス」と「インスタンス」という性質の異なるオブジェク
>トであるに過ぎない
静的かそうでないかの違いということですよね?

>オブジェクト指向は、「すべてがオブジェクトとして存在する」こ
>とに意味がある
これはどういうことなのでしょうか?

質問をいっぺんにしてしまい申し訳ございませんが、よろしくお願い致します。

補足日時:2009/06/13 13:55
    • good
    • 0

※Javaに詳しいわけではないので、言語にフィットした回答ではないかもしれません。


まず、インスタンスの引渡しは引数と同じ実現性を持つので、お考えの通り大きな差異はありません。つまり使い勝手や概念としての使い分けになることは分かると思います。

非staticなメソッドからはインスタンスの指定が楽で間違いを起こしにくくなります。また外部からの呼び出しはコードが若干冗長になるので、特別理由が無い限り非staticにすべきです。
メンバに影響のあるメソッドはクラスの状態遷移なので、引数でインスタンスを渡すとなると参照で渡す必要があり、リスクは増えます。

質問にあるユーティリティがどういったものかは分かりませんが、敢えてstaticメソッドにする場合は幾つかあります。
メンバに影響が無く、処理の対象が特定の変数とは限らない場合、これはクラスに依存しないユーティリティなのでstaticにすべきです。
関数オブジェクト(Javaでの呼び方は知りません)として利用できるので、それで楽に実装できるのであればそれは有用な事です。
他にも使いどころは色々ありますが、一般化した説明がしにくいので割愛します。

staticメソッドに限りませんが、使いどころは必要となる場面に出会わない限り理解しにくい事が多いです。こういうものがあるという事さえ知っていれば、必要になったとき自ずと使えます。

この回答への補足

質問者です。このスペースにまとめて書かせて頂きます。

夢うつつずっと考えていてふっと思ったことですが、質問文の※を
やってしまうと、そのメソッドはただの関数になってしまう?
オブジェクト指向のメリットとは、オブジェクトとして、さまざまな
種類に関する状態をまとめて扱えることですよね?
なので、普通は、オブジェクトに影響を与える非staticメソッドに
なっているはず?

だけど、たまに、日付を変換するときとか、その場限りの結果だけほしいとき(オブジェクトの状態(特徴?)としてもつ意味がないとき?)が
あります。
そういうオブジェクトに関係ないメソッドはそのクラスにまぎれさす
必要がないので、しかも他でも使いそうだから、別のクラスのメソッド
として作ろう!
そして、この場合のメソッドって、ただの関数としての役割で十分だ
よね?だったらわざわざメモリを増やしてまでオブジェクト作らなく
てもいいか。

ということですかね?
オブジェクトで扱えることって、メモリの消費を犠牲にしてでも
一回きりの関数と比べたとき、便利なものですよね?
だけど逆に、オブジェクトで扱う必要がないのに、無理にオブジェクト
として扱ってもそれは、犠牲を払った分の効果がないので、そこで
staticという仕組みがあるのですかね?

どうでしょうか。かなりまとまりのない文ですみません。
よろしくお願いします。

補足日時:2009/06/12 08:20
    • good
    • 0

>「じゃあこのメソッド内でインスタンス変数を使わないで


>引数で渡せるように作れば、インスタンスに依存しないの
>でstaticにしていいの?」

foo.bar();

ではなくて、

bar(foo):

とする。ということですね。その通り、同じことです。

オブジェクト指向の意味がない、というよりも、
「みんなが見慣れた書き方」に合わせた方が何かと都合がよい、という程度です。
    • good
    • 0

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