C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: enumの継承?


(過去ログ 21 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■9118 / inTopicNo.1)  enumの継承?
  
□投稿者/ ぼのぼの (105回)-(2007/10/19(Fri) 12:46:40)

分類:[C#] 

こんにちは。例えば以下のようなenumがあったとします。

public enum MusicFormat { WAV, MP3 }
public enum MusicFormatApple { WAV, MP3, AAC }
public enum MusicFormatSony { WAV, MP3, ATRAC }
public enum MusicFormatMS { WAV, MP3, WMA }

これらが、下記のような関係にあった場合、

                   MusicFormat
                        △
                        │
        ┌───────┼────────┐
MusicFormatApple  MusicFormatSony   MusicFormatMS

クラスだったら
public class MusicFormatApple : MusicFormat
のように書きますが、enumの場合似たような記述方法はあるのでしょうか?
それとも、enumでの継承的な概念は何らかの理由でサポートされていない?
一応Googleなどで検索してみたのですが、
キーワードが悪かったのか有用な情報は見つけられませんでした。

引用返信 編集キー/
■9121 / inTopicNo.2)  Re[1]: enumの継承?
□投稿者/ 未記入 (128回)-(2007/10/19(Fri) 13:03:49)
enumはSystem.Enumからの派生クラスであり、System.EnumはSystem.ValueTypeからの派生クラスです。
System.ValueTypeからの派生クラスは値型のクラス(構造体)なので.NETの多くからは継承できないはずです。
どうしても継承したい場合は普通のクラスに定数フィールドを並べて継承するしかなさそうですね。
引用返信 編集キー/
■9124 / inTopicNo.3)  Re[2]: enumの継承?
□投稿者/ Hongliang (200回)-(2007/10/19(Fri) 13:19:04)
Hongliang さんの Web サイト
例がどうにも。
[Flags] enum MusicFormats { None = 0, Wav = 1, Mp3 = 2, Aac = 4, Atrac = 8, Wma = 16, ... }
MusicFormats appleSupported = MusicFormats.Wav | MusicFormats.Mp3 | MusicFormats.Aac;
とすべき状況ですからねぇ。
// 64bits でも足りないとなるとやっぱり列挙体風のクラスを作ることになりますけど。
引用返信 編集キー/
■9125 / inTopicNo.4)  Re[1]: enumの継承?
□投稿者/ 魔界の仮面弁士 (480回)-(2007/10/19(Fri) 13:37:56)
No9118 (ぼのぼの さん) に返信
> enumの場合似たような記述方法はあるのでしょうか?
無いと思いますが、それができないと困るような状況に陥っているのでしょうか?

> それとも、enumでの継承的な概念は何らかの理由でサポートされていない?
enum に限らず、値型(ValueType)はすべて継承できないと思います。少なくとも C# の世界では。
struct AAA にしても、enum BBB にしても、自動的にシールされますし。

# SDK で、コンパイラ エラー CS0509 について調べると、C# においては
# 「既定では、構造体はシールされています。」という表現が見つかります。

> public class MusicFormatApple : MusicFormat
低レベル言語でも良いのなら、MSIL を使って
 .class public auto ansi sealed MusicFormatApple extends MusicFormat {
のように書く事は可能ですが、C# の場合、無理にそのような方を定義しても、
コンパイラ エラー CS0648 『'型名' はこの言語によってサポートされていない型です。』となります。
引用返信 編集キー/
■9223 / inTopicNo.5)  Re[3]: enumの継承?
□投稿者/ ぼのぼの (106回)-(2007/10/22(Mon) 13:23:08)
No9121 (未記入 さん) に返信
> enumはSystem.Enumからの派生クラスであり、System.EnumはSystem.ValueTypeからの派生クラスです。
> System.ValueTypeからの派生クラスは値型のクラス(構造体)なので.NETの多くからは継承できないはずです。
> どうしても継承したい場合は普通のクラスに定数フィールドを並べて継承するしかなさそうですね。

なるほど。C#でenumの継承が使えないことはわかりました。

No9124 (Hongliang さん) に返信
> 例がどうにも。
> [Flags] enum MusicFormats { None = 0, Wav = 1, Mp3 = 2, Aac = 4, Atrac = 8, Wma = 16, ... }
> MusicFormats appleSupported = MusicFormats.Wav | MusicFormats.Mp3 | MusicFormats.Aac;
> とすべき状況ですからねぇ。
> // 64bits でも足りないとなるとやっぱり列挙体風のクラスを作ることになりますけど。

いやいや、待ってください。
ビットのフラグで値を割り振るのは「重複可能な属性」の場合ではないですか?
#例えばFileAttributesみたいな。
これが、SupportedFormatという属性を表すならその通りなんですが、
ここでは純粋にフォーマット形式を表す値として例に挙げたつもりでした。
例えば、ConvertなりExportなりといったメソッドがあってその引数に使うような。

No9125 (魔界の仮面弁士 さん) に返信
> ■No9118 (ぼのぼの さん) に返信
>>enumの場合似たような記述方法はあるのでしょうか?
> 無いと思いますが、それができないと困るような状況に陥っているのでしょうか?

あ、いや、別にそういうわけではないです(^^;
ただの興味です。

ただ、そういう状況を無理くり考えてみると。

例えば、何らかの情報を保持するクラスがあって、
public enum FileFormat {XML, Binary};
virtual void Export(string fileName, FileFormat format)
と定義されてたとします。

で、A,B,Cという派生クラスがあって、
CクラスだけCSV形式でのエクスポートにも対応したくなった、という場合。

まぁCsvExportという別メソッドを作っちゃえばいいわけなんですが、
FileFormatを継承して「CSV」だけ追加したenumを作って使えたら、
ちょっと便利かな?などと思いまして。


つまりですね、知りたかったのは、
「『出力形式』みたいなものを表すクラスなり列挙体なり」に「継承」という概念を持ち込むことが、
オブジェクト指向型言語での設計における一般的な指針に反するのか、
それとも単に「C#ではenumの継承は無理よ」という言語仕様上の制約の結果に過ぎないのか。

上記例のような設計が、少なくともC#でenumを使っては無理、てことで、
じゃあ代わりにclassを使って同様のことを実現するのは、
設計としては間違っていない?それとも普通はやらない?ということなのでした。
引用返信 編集キー/
■9241 / inTopicNo.6)  Re[4]: enumの継承?
□投稿者/ 未記入 (129回)-(2007/10/23(Tue) 00:53:31)
No9223 (ぼのぼの さん) に返信
> つまりですね、知りたかったのは、
> 「『出力形式』みたいなものを表すクラスなり列挙体なり」に「継承」という概念を持ち込むことが、
> オブジェクト指向型言語での設計における一般的な指針に反するのか、
> それとも単に「C#ではenumの継承は無理よ」という言語仕様上の制約の結果に過ぎないのか。
>
> 上記例のような設計が、少なくともC#でenumを使っては無理、てことで、
> じゃあ代わりにclassを使って同様のことを実現するのは、
> 設計としては間違っていない?それとも普通はやらない?ということなのでした。

僕はやらないかも。
1つの列挙型として定義しておいて、使用不可のクラスに突っ込まれた時は引数が適切じゃないよ例外を発生させるとか。
引用返信 編集キー/
■9243 / inTopicNo.7)  Re[4]: enumの継承?
□投稿者/ 魔界の仮面弁士 (481回)-(2007/10/23(Tue) 12:51:10)
No9223 (ぼのぼの さん) に返信
> 「『出力形式』みたいなものを表すクラスなり列挙体なり」に「継承」という概念を持ち込むことが、
> オブジェクト指向型言語での設計における一般的な指針に反するのか、
> それとも単に「C#ではenumの継承は無理よ」という言語仕様上の制約の結果に過ぎないのか。

エクスポート方法を拡張可能にするのであれば、データクラスに Export メソッドを
付加して、そこに列挙体で方法を示す設計は避けた方が良いかと思います。
エクスポート処理のみを担当するクラスを作り、そこにデータクラスを渡す設計の方が
後の拡張がやりやすいかと思いますし。
(その逆に、データクラスにエクスポートクラスを渡す設計でも良いですけれど)


もし、出力形式を列挙体で示すにしても、それは enum を継承させようとするのではなく、
 void Export(string, FileFormat) // WAV, MP3用
 void Export(string, FileFormatMS) // WMA用
のように、オーバーロードで解決した方が分かりやすいように思います。

というのは、もしも FileFormat を 継承した FileFormatMS 列挙体を作れたとしても、その場合、
 void Export(string, FileFormat)
を受け付けるメソッドに対して、
 obj.Export(file, MusicFormatMS.WAV); // 1
 obj.Export(file, MusicFormatMS.WMA); // 2
のように呼び出したときに、どういった結果になるかが不明瞭になってしまうからです。
Export メソッドの内部実装によって、結果が異なってしまうでしょうしね。

(案1) FileFormatに無い値「WMA」が渡されたら、例外を発生させる。
 if(value == FileFormat.WAV) { WAV出力(); }
 } else if(value == FileFormat.MP3) { MP3出力(); }
 } else { throw InvalidEnumArgumentException(); }

(案2) FileFormatに無い値「WMA」が渡されたら、WAV 扱いになる。
 if(value == FileFormat.MP3) { MP3出力(); }
 } else { WAV出力(); }

(案3) FileFormatに無い値「WMA」が渡されたら、何もしない。
 if(value == FileFormat.WAV) { WAV出力(); }
 } else if(value == FileFormat.MP3) { MP3出力(); }
 } else { return; }
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -