- PR -

C#の「VBのMyClass」にあたるキーワードは?

投稿者投稿内容
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-08-20 07:49
そのコード、おかしいと思いませんか?または、どうテストしたらいいのでしょう?

従業員に歳を尋ねたら「二十歳です」と、返ってくるのですよ?なのに、「じゃぁ、飲みに行きましょう」とさそうと、「20歳未満なので飲めません」って言われる。「どっちやねん!?」てなりません?

コッソリ(PMで)書名を教えて下さい。
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2007-08-20 10:34
プログラミング言語で用意されている構文は、それぞれにその構文が表す意味があります。最近の人間に近い言語(高級言語)は特に。
例えば.NET言語のプロパティはそのオブジェクトの属性や状態、オブジェクトが持っているモノなどを表します。
これはもちろんgetXXX(),setXXX()というメソッドを作って同じ動きをするプログラムを作ることはできます。
逆に、プロパティをgetするとテキストボックスのテキストをクリアするようなプログラムも作れます。
しかし、同じ動きをするプログラムを作れるからといって、それぞれの構文が表す意味と異なる使い方をするソースコードは後で読む人に混乱とストレスを与えます。

heiさんのソースでは、Employee.AgeはPerson.Ageをオーバーライドしていますよね。
すると、読み手は
の中でも従業員という種類のは、年齢の計算方法がとは異なる」
という意味を読み取ります。(heiさんがそういう意図で書いたかどうかに関らず)
そして、CanDrinkプロパティを見ると、
年齢が20を超ている場合お酒を飲める、そうでない場合お酒を飲めない」
というheiさんがソースコードで表現する世界のルールが読み取れます。

これはheiさんは表現したい世界ではありませんよね。
間違っていそうな場所はふたつあります。
ひうつは「Employee.Ageが実はAgeではない」ということ。
例えばこの年齢は「帳票表示用の年齢」みたいなものかも知れません。
それならPersonにCyouhyouAgeというプロパティを作り、そこでは単にAgeを呼ぶようにしましょう。
そしてEmployeeはCyouhyouAgeをオーバーライドします。
もうひとつ考えられるのはお酒を飲めるかどうかのルールが間違っているということ。
本当に「年齢が20を超ている場合お酒を飲める、そうでない場合お酒を飲めない」のですか?
20歳になってもまだお酒を飲めないようなパターンはありませんか?
具体的には従業員という種類の人は20歳になってもしばらくはお酒が飲めないということにはありませんか?

ソースコードは対象の世界を表現する文章です。
物書きになったようなつもりでソースコードを書いてみましょう。

引用:

ぶさいくろうさんの書き込み (2007-08-19 17:30) より:
いらない。どころかサポートしないで欲しいな。


そうですね。
MyClassはどういう意味合いを表すキーワードとして使われるんでしょうね。
hei
ベテラン
会議室デビュー日: 2006/09/07
投稿数: 78
投稿日時: 2007-08-20 12:45
このサンプルの内容に意味ありません。
タイトルのことを知りたかっただけです。
書籍では18才以上はCanVoteとなっていますが、
少し変えて書き込みました。
もちろん内容がおかしくないことに越したことはありませんが、
プログラム言語の構文を分かりやすく説明・理解するには
簡潔に表現できる方が重要だと思います。

あと、私が余計なことを書いたのが原因で違う方向に向かっていますが、
私は選択肢が多くあることはいいことだと思います。
他人が書いたソースを読むときでも、MyClassのようなキーワードで書かれていたほうが分かりやすいと思いますけどね。

(人それぞれなので、これ以上どっちがどうというつもりはありません。)
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2007-08-20 14:14
少し気を悪くされてますか。
heiさんのソースに突っ込んだのは、そのソースが対象の問題領域を表現した結果だとすると、うまく表現できない原因が「MyClassがない」ということではなく「表現の仕方が間違っているのでは?」ということを言いたかったからです。ですので、
引用:

heiさんの書き込み (2007-08-20 12:45) より:
プログラム言語の構文を分かりやすく説明・理解するには簡潔に表現できる方が重要だと思います。


MyClassの効果や使い所を示すための仮のソースだというなら突っ込むところじゃなかったですね。

引用:

heiさんの書き込み (2007-08-20 12:45) より:
あと、私が余計なことを書いたのが原因で違う方向に向かっていますが、
私は選択肢が多くあることはいいことだと思います。


基本的にこの掲示板はおせっかいが多いので、heiさんがMyClassを使いたがっているが考え方を変えることでheiさんの問題を解決できるのではないか、と思う人が多いです。
ですので「出来ますか?○か×か?」といっても△が返ってきたりします。

ここは情報交換の掲示板ですので、他の人と意見をぶつけ合うと新しい発見があるかもしれませんよ。
「人それぞれ」はそうなんですが、そう言ってしまっては全部が「人それぞれだから」で終わってしまいます。
最終的に納得できないままスレッドが終わることももちろんありますが、相手を打ち負かすとか勝ち負けとかそういうことではなく自分と違う考えに触れるというのは自分の成長につながると思います。

ちなみに「選択肢が多くあることはいいこと」というのは、私は無条件には賛成しかねます。
今は時間が無いので詳細は後で。
hei
ベテラン
会議室デビュー日: 2006/09/07
投稿数: 78
投稿日時: 2007-08-20 15:22
引用:

一郎さんの書き込み (2007-08-20 14:14) より:
少し気を悪くされてますか


そんなことありませんよ。
ただ書き方はよくありませんでしたね。
失礼しました。

引用:

相手を打ち負かすとか勝ち負けとかそういうことではなく自分と違う考えに触れるというのは自分の成長につながると思います。



そうですね。
書き込みお待ちしてます。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-08-20 22:17
ん。。。適当に省略するとして。
コード:
class Person {
    private DateTime birthday;

    public int Age {
        get {
            int age = DateTime.Now.Year - this.BirthDay.Year;
            if (DateTime.Now.DayOfYear < this.BirthDay.DayOfYear) age--;
            if (age < 0) thow new ApplicationException("生まれてないよ!?");
            return age;
        }
    }

    public virtual bool CanDrink {
        get {
            return (this.Age >= 20);
        }
    };
}


ここで、Age は変えちゃいかんと思うのですよ。「年齢」の、定義は不変です。数え年というのは、定義ではなく、数え方の基準を「正月一日に年を取る」と変えたものです。このとき、元の誕生日は考慮しません。なので、Age は変えずに、たとえば、次のような実装をする、と。
コード:
class Employee : Person {
    public int 数え年 {
        get {
            return DateTime.Now.Year - this.BirthDay.Year;
        }
    }
}



 たとえば、「俺は“歳”を聞かれたら必ず“数え年”で答えるんだっ!」って人をクラス化する...う〜ん。これは、困った。
コード:
class ひね坊 : Person {
    public new int Age {
        get {
            return DateTime.Now.Year - this.BirthDay.Year;
        }
    }
}




 それはそうと、C# に ThisClass なんてのができたとして、Person の CanDrink の判定に用いる Age を ThisClass.Age と参照したとして。
 それこそ、2007-08-19 17:01 の、「ただこれ嵌ったら原因がわかりにくいところ」ではないでしょうか。つまり、2007-08-20 07:49 の「従業員に歳を尋ねたら「二十歳です」と、返ってくるのですよ?なのに、「じゃぁ、飲みに行きましょう」とさそうと、「20歳未満なので飲めません」って言われる。「どっちやねん!?」てなりません?」のことですけど。
 CanDrink も Age も、公開されている以上、次のような使い方をしてもいいわけです。
コード:
    if (emp.Age >= 20) {
        if (emp.CanDrink) {
            return @"飲めや歌えの大騒ぎ";
        } else {
            return @"俺の酒が飲めねぇってか、おらぁ!";
        }
    } else {
        return @"未成年は、しゃぁないわな";
    }


 本来なら「未成年お断り」のはずが、「俺の酒が飲めんのか!」となるわけです。
 ということで、やっぱり「その本の例が悪い」。


最初に戻って。
引用:

問題になることは少ないと思いますが、
次のように常に派生クラスではなく基本クラスのメソッド・プロパティを使用したい時もあると思います。
VBではMyClassキーワードで解決できますが、
C#でそのようなキーワードが用意されていなければどうしたらよいですか?


 設計が悪い。で、片付けていいですか?
 つまり、「変えていいよ」と公開しているものを、「やっぱり変えないでね」って言っているわけです。だったら最初から「変えちゃダメ」にしておきませんか。
 あ、VB はいいんですよ、VB は。だって、開発者だけをターゲットとした言語じゃないのだから。
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2007-08-21 13:19
「選択肢が多くある」というと、単純にはシンタックスシュガーが連想されます。
これは過度でなければ基本的にあっても良いものと思っています。
が、この場合私が使っているシンタックスシュガーという言葉は「表現する意味が同じ構文」という意味であって「走らせた時に同じ動作ができる構文」という意味ではありません。
先に挙げたプロパティの例では、プロパティとメソッドはどちらも何らかの処理をして何らかの値を返すようなことができます。
ではプロパティはメソッドのシンタックスシュガーでしょうか。つまりプロパティはメソッドを別の書き方で書くような使い方をする構文でしょうか。
そうではないことはお分かりだと思います。プロパティ構文を使う場所というのはプログラマがメソッドとプロパティどちらを使うか選ぶまでもなく決まっています。
それは、プロパティを使うことによって表現される意味というものがあるからです。具体的には属性や状態などということです。
ですので、.NETでプロパティという構文が増えたからといって選択肢が増えたという見方はしません。
プロパティがあることで、逆にメソッドは「属性や状態を設定取得する以外の処理」というような意味合いが強くなります。
C#でJavaのようにgetName(),setName()のようなメソッドが定義されていたら、何か特別な理由があるのだろうかと思ってソースをじっくり確認しちゃいますよね。

今回の話のMyClassも、すでにある書き方のシンタックスシュガーというわけではないですね。
ですので、選択肢というよりは新しい表現方法が作られたと考えるのがよいと思います。
人クラスで年齢をvirtualで定義し従業員クラスでそれをオーバーライドするということは、
「人の年齢というのはこう計算するが、従業員の年齢だけは特別にこう計算する」
という「年齢」という言葉の意味を定義しているわけです。
そして、「年齢が20以上ならお酒を飲める(ただし年齢というのは人でいう年齢)」というビジネスルールを見ると、明らかに人でいう年齢の定義が従業員でも生きていることが分かります。
こうなると、もはやオーバーライドは定義を置き換えるという意味合いではなく従業員年齢とでもいうようなものを別に定義する二重定義的な意味合いになります。

もし酒がのめるかどうかの判定やその他のビジネスルールをビジネスルールクラスといったようなもので一元管理するような作りにした場合にはどうしたらいいでしょうか。
つまり、外部から人年齢を使いたい場合です。
MyClassが一般的に使われるようになって、オーバーライドの意味合いが変わって、人年齢と従業員年齢ふたつの定義があるということならもちろん外からも人年齢を使いたいですよね。publicなんですから。
すると、オーバーライドされている階層のどのクラスに定義されているメンバーを使うかを指定するような構文が作られるはずです。
もしMyClassが一般的に使われるようになって、オーバーライドがオーバーライドではないというコンセンサスが開発者の間で出来上がれば、必ずそういった構文ができます。MyClassに限らずXXXClassの年齢といったような。
そう考えるとMyしか使えないのは不完全で中途半端ですね。

と、MyClassがあるかないかでここまで考えるのは考えすぎでしょうか。
しかし、プロパティがあることでメソッドの意味合いが変わったように、MyClassがあればただ選択肢が増えるといったような単純な話ではないということはガッテンして頂けましたでしょうか。

[ メッセージ編集済み 編集者: 一郎 編集日時 2007-08-21 13:38 ]
hei
ベテラン
会議室デビュー日: 2006/09/07
投稿数: 78
投稿日時: 2007-08-21 21:39
言われてみると確かにそうですね。
参考書を読んでいてこのような例が出てきましたが、
私はこれまでこのような実装をする必要性はありませんでしたし、
他に適切な例もうかびません。
このようなものが必要だということは、
確かに「設計が悪い」のかもしれませんね。

今回は質問した内容以外にも
とても参考になりました。
みなさんありがとうございました。
今後もよろしくお願いします。

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