- PR -

特集「私がJavaからC#に乗り換えた10の理由」について

投稿者投稿内容
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2003-07-14 17:45
忙しかったので、しばらく書き込みしていませんでしたが、スレッドのアイコンが激しく炎上していましたので、記念書き込みさせていただきます。

>悪夢を統べるもの さんの書き込み
>だから,おそらくC#でいう「プロパティ」というのは,オブジェクト指向を分かってるプログラマー
>ならば,可能な限りその利用を避ける危険な機能だと考えられます.

プロパティというのは、メソッドと同じでサービスを提供するものです。
JavaではgetXX(),setXX()というようにメソッドの名前によって、そのサービスに「属性にアクセスする」というような意味を付加しているのだと思います。
C#ではプロパティというサービスに、「属性にアクセスする」ような意味を持たせています。
(もちろんgetXX(),setXX()にそういう意味を与えるというルールでプログラムを作ることもできる)

たとえば、「人」クラスに年齢というフィールドがあったとします。
しかし「生年月日と現在の日付から年齢が計算できるから、年齢というフィールドは無くしましょう」
ということになった場合、年齢というフィールドを外部からアクセスできるようにしていると困りますが、プロパティによって年齢を取得するというサービスを提供していた場合、計算して年齢を返してやればOKです。(派生属性ってやつですね)

JaveとC#ではサービスに「属性にアクセスする」という意味を持たせる方法が異なるだけで、やっていることは同じなんでしょうね。

あと、デリゲート・イベントについてですが、私は分かりやすいと思いました。
eventというメンバが直感的にとらえやすいですよね。
delegeteっていうクラスは何者なんだ、ということに関しては、
「オブジェクト指向に必要な物を実装して、必要ないものはなるべく取り入れない。それでこそプログラミングが解りやすくなり効率が上がる」というJavaの姿勢には合わないということではないでしょうか。
逆に「指向に囚われないで何でもやる。それでこそ効率が上がる」という考えのC#だからオブジェクト指向にわざとピッタリ合わせていないわけです。
これは、この掲示板では何回も言われていますが「どちらが良い」というものではないと思います。

その他の処理効率等については良く分かりません。



とほとんどJavaを使ったことが無い人間が書いてみる・・・。
英-Ran
ベテラン
会議室デビュー日: 2002/06/12
投稿数: 55
投稿日時: 2003-07-14 20:38
英-Ran@Java信者です

# めんどくさいので、言語話を始めてしまいます

引用:

JaveとC#ではサービスに「属性にアクセスする」という意味を持たせる方法が異なる
だけで、やっていることは同じなんでしょうね。



その理解で私も正しいと思います。でも、プロパティをset、getで記述できるって部
分はそんなに便利なのかなあと個人的には疑問に思ってます。

Javaだと、
コード:
public void setHoge(Hoge hoge) {

}

public Hoge getHoge() {
}


と書くところが
コード:
public Hoge hoge {

set{
}
get{
}
}


となるだけでしょ。確かに、言語でプロパティの書き方が明示されているのがいいの
はわかるのだけど、ユーザとしてこのシンタックスが採用されたことにそれほど利点
があるとは思えないのだけれど。

# foo.setHoge(bar)をfoo.hoge = barと書けるのが便利なのは理解できるけど

引用:
あと、デリゲート・イベントについてですが、私は分かりやすいと思いました。
eventというメンバが直感的にとらえやすいですよね。
delegeteっていうクラスは何者なんだ、ということに関しては、
「オブジェクト指向に必要な物を実装して、必要ないものはなるべく取り入れない。
それでこそプログラミングが解りやすくなり効率が上がる」というJavaの姿勢には合
わないということではないでしょうか。



うーむ、objectさんは最後まで納得してくれなかったけれど、eventとdelegateという
のは別の概念だし使用範囲も一致するわけではないので別々のものとして扱って欲し
いところ。autumnさんのC#の連載でもそのように書かれていたので、私の偏見という
わけではないようだし。

で、delegateですが、例えば、http://www.atmarkit.co.jp/fdotnet/csharp_abc2/csabc2_017/cs2_017_01.htmlを見
た限りだと、namespace Sample001で定義されたdelegateの引数は二つなのに、使って
る場所では一つしか引数がない。いったい、どのような過程を通してイベントが呼ば
れているのかソースコードだけからはわからないでしょ。しかも、イベントドリブン
機構が必要な場面のすべてでdelegateが有効なわけじゃなくて、前にも挙げたSAX API
の呼び出しの場合には、クラスベースのイベント機構の方が直感的だし単純に書ける
(と私は思う)。そうすると、ユーザ(=プログラマ)はdelegateとクラスベースの
イベントドリブンの両方を理解しなければならなくなる。

それだったら、Javaの無名インナークラス+シンタックスシュガーとかJavaScriptの
Functionオブジェクト+型機構とか導入するとかしたほうがよかったんじゃないかと
(そのほうが、おじまさんの主張するMicrosoftの主義に会うし、ソースも分かりやす
くなる……と思う。実は自信なし)。

ここらへんの話は、testmlでも挙げられていたけれど、
http://java-house.jp/ml/archive/j-h-b/001960.htmlを参照のこと。
でも、ここを読むとまつもとさんの挙げている例はC#のそれとは違うもののような……

[ メッセージ編集済み 編集者: 英-Ran 編集日時 2003-07-14 20:42 ]
mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2003-07-14 21:10
こんばんは、meiです。

引用:

# foo.setHoge(bar)をfoo.hoge = barと書けるのが便利なのは理解できるけど



私の場合、このメリットしか思いつきませんでした(汗)。
まぁ、この例だけだと、ありがたみもイマイチですが、

foo.hoge += bar;

↑みたいに、現在の値を取得して演算して戻すみたいなのがさらに便利。

でも、get,setの記述方法については、私もあんまり気に入ってません。
特にvalueなんてよく使うモノがキーワードになっちゃっているので、
変数名のレパートリーが減ってしまいましたよ(笑)。

クラスを作る側はsetter/getterで全然構わないのですが、
使う側はプロパティの方が楽かな?って感じでしょうか。

引用:

で、delegateですが、例えば、http://www.atmarkit.co.jp/fdotnet/csharp_abc2/csabc2_017/cs2_017_01.htmlを見
た限りだと、namespace Sample001で定義されたdelegateの引数は二つなのに、使って
る場所では一つしか引数がない。



サンプル見た限り、ちゃんと引数2つ渡していません?
多分、見間違えだと思うのですが、

target.sampleEvent += new SampleEventHandler(target.handler);
↑これって、イベントの登録で、

target.sampleEvent( target, EventArgs.Empty );
↑これが、イベントの発火です。

例えば、
target.MyEvent += new MyEventHandler(target.Service1);
target.MyEvent += new MyEventHandler(target.Service2);
target.MyEvent += new MyEventHandler(target.Service3);
とかして、
target.MyEvent(foo, bar);
とかすると、Service1,2,3がすべて呼び出されます。

個人的に、delegate/eventは、
Observerパターンの言語レベルでのサポートと捉えてます。
個人的に結構使うパターンなので、自作しなくて便利程度に思っています(笑)。


[ メッセージ編集済み 編集者: mei 編集日時 2003-07-14 21:12 ]
英-Ran
ベテラン
会議室デビュー日: 2002/06/12
投稿数: 55
投稿日時: 2003-07-14 21:42
引用:

meiさんの書き込み (2003-07-14 21:10) より:
こんばんは、meiです。



こんばんは、この会議室もすっかり落ち着いちゃいましたね。

引用:

サンプル見た限り、ちゃんと引数2つ渡していません?
多分、見間違えだと思うのですが、

target.sampleEvent += new SampleEventHandler(target.handler);
↑これって、イベントの登録で、


この部分のことです。この構文を普通のクラスと同様に見ると引数ひとつのコンストラクタに見えるけれど、それがソース上に明示されてないでしょう? それに同じ名前でイベントの発火部分の定義まで行っているので、いったいSampleEventHandlerが何者なのかはクラスベースの考え方では理解できないようになっていると私には感じるのです。

例えば、まつもとゆきひろさんの言う方法だったら、
コード:
namespace Sample001 {

class Class1 {
public event Method(object sender, EvnetArgs e) sampleEvent;

public void handler( object o, EventArgs e) {
Console.WriteLine("handler called");
}

[STAThread]
static void Main(string[] args) {
Class1 target = new Class1();
target.sampleEvent += target.handler;
target.sampleEvent( target, EventArgs.Empty );
}
}
}


もっと直感的で、簡潔なコードが書けるし、delegateキーワードがいらなくなります(まあ、その代わりMethodオブジェクトが必要だけど)。

[ メッセージ編集済み 編集者: 英-Ran 編集日時 2003-07-14 21:43 ]
mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2003-07-14 22:53
meiです。

引用:

(ソースは略)
例えば、まつもとゆきひろさんの言う方法だったら、
もっと直感的で、簡潔なコードが書けるし、delegateキーワードがいらなくなります



確かにこっちの方が読みやすいですね。

正直言って私もC#を勉強したての頃、
event/delegateの書き方が馴染めませんでした。

見えないところでコンパイラがクラスやらメソッドをこっそり作っているようで、
楽させようとしているのは分かるけど、かえって分からないぞ〜とか思ったりも。

私の場合、C#はほとんど趣味で使っているので、
ギミック沢山で面白がって使ってますが、
間違った使い方されたときは、怖そうですね〜(汗)

私自身、C++から直接C#に来たので、
大抵のことはC++に比べりゃ・・・とか思ってしまいます(笑)。
流石に「Modern C++ Design」とかの超絶templateを見て、
C++についていく自信がなくなったのですが(苦笑)。

話はそれましたが、私がC#を使っている理由は、C#自体というよりも、
.NET Framework(というか、ASP.NETとADO.NET)が便利だというのが一番の理由かな?

単純に言語の好き嫌いでしたら、個人的にはPythonが一番好きなんですが、
イマイチマイナーで仕事で使える機会がないんですよ(笑)。
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2003-07-15 07:27
やっと落ち着いてきたかも(落ち着くまで様子見てました)。

delegateについてですが、私は
コード:
target.sampleEvent += new SampleEventHandler(target.handler); 


の方を押します。これのほうがオブジェクトって感じがして直感的に感じます。
要はdelegateがclassとかstructとかと対等の意味を持っていて、型を宣言するものなんだよ、と考えやすいし。
コンストラクタの定義がソースにないっていうのは確かにそうですが、それいったら「すべてのクラスはオブジェクトから継承する」とかだって書いてません。class定義の「ルール」があるようにdelegate定義の「ルール」があるってことだと思えば。
ついでに言えば、
コード:
delegate void SampleEventHandler(object sender, EventArgs e);


と宣言する事は型(classと同じ)を定義し、
コード:
new SampleEventHandler(target.handler); 


によってそのインスタンスが生成された、という意味になるわけで。
コード:
target.sampleEvent += target.handler;


これだと「どの型のインスタンスが生成されたの?」になってしまうような。いや、正確にはメソッド自体が型であって、new target.handlerに修正してこれは型をインスタンス化しているのだ、と考えれば良いと思いますが、それだと例えばtest1 classのインスタンスのメソッド
public void test1method(object sender, EventArgs e){...}

test2 classのインスタンスのメソッド
public void test2method(object sender, EventArgs e){...}
の型は同じなのか違うのか。まぁとりあえず、現状のように型を定義してそのインスタンスを作ってそれを(イベントに)登録する、といったほうが型システムにおいて自然だろうな、とは思います。
いのつち
ベテラン
会議室デビュー日: 2002/05/14
投稿数: 73
投稿日時: 2003-07-15 10:11
私はプロパティ支持派です。

オブジェクトの状態(属性)を示すための型システムだと考えています。
フィールドが本来その意味にあたるのかもしれませんが、データ保護から
大抵は、public ではないフィールドとしてカプセル化されますよね。
結果的には、フィールドは、オブジェクト内のメモリだと考えます。


確かに、getXXX setXXXX メソッドで実現できますが、
メソッドは、あくまでオブジェクトの振る舞いを定義するものであって、
状態(属性)を示すものではないと考えると、
(このあたりJava派の方と考え方はちがうのかも)
言語仕様として、明確に外部から通信可能な状態(属性)を示す「プロパティ」という定義は
有効だと思います。


また、(オブジェクトの状態(属性)を示すものとして)プログラマの意図が宣言されており、
メソッドとは明確に区分されているので、
リフレクションでオブジェクトの(属性)状態を取得するという目的の
ためには、プロパティまたはフィールドのみを調べればよいことになります。

Javaは詳しくないのですが、同等のことを行う場合、
 get〜で始まるメソッドを抽出したりするのでしょうか。


あと、些細なことですが、
IDEのインテリジェンス入力補助の機能でも、getX より Xと
一文字で目的の候補にたどり着けるってとこもいいなと思っています。

そういう意味では、event キーワードも、 
 AddListener RemoveListener を定義した型システムといえます。
 event もプロパティと同様の理由で有効だと思います。

ちなみに、だからJavaがどうこうと言うつもりはありません。
あくまで、C#のプロパティ・イベントという考え方に共感し、
支持しているというだけです。
いまい
会議室デビュー日: 2002/07/02
投稿数: 13
投稿日時: 2003-07-15 11:19
引用:

Javaは詳しくないのですが、同等のことを行う場合、
 get〜で始まるメソッドを抽出したりするのでしょうか。


それでもできますが、Introspectorを使ってBeanInfoPropertyDescriptor経由で取得するのが本筋かな。

これがクセモノ(?)で、fooとかbarならgetFoo(), setBar()なんだけど、aFooとかすると、getAFoo()になって、Introspectorはプロパティ名をAFooと解釈する(ほんとは、aFooなのに)。
これ(Introspector.decapitalize()の仕様)が好きじゃない。

紛らわしい名前付けるほうが悪いんだけど、そんなときもあるでしょってことで。

[ メッセージ編集済み 編集者: いまい 編集日時 2003-07-15 11:48 ]

スキルアップ/キャリアアップ(JOB@IT)