- - PR -
VBにおいて動的にクラスを設定する方法
投稿者 | 投稿内容 | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-05-09 17:17
evalって、JScript.NETにしかないんですよね。でもってHELPを見る限りJScript.NETのevalで望んでいる事が実現できそうなんですけど、クラスのインスタンスを生成できなかったんでしょうか? #そのためにJScript.NETを採用したいとは思わないけど・・・・ | ||||||||||||||||||||
|
投稿日時: 2007-05-09 20:49
計算クラスの追加やメンテナンスをさとるさんが行うのでしょうか。 各使用者が派生クラスを作ってプラグインのように追加していくのでしょうか。 自由に計算クラスがどんどん増えていく状況ではなく、 システム側から必要時に提供していくのであれば いわゆるファクトリークラスを用意したほうがよいような気もします。 インスタンス化処理自体はメソッドの中に隠蔽しておいたほうがよさそうですよね。 public class CalculatorFactory public function CreateCalculator(name as string) as clsSuperClass if ( name = "clsSubClassA" ) then return new clsSubClassA() else if ( name = "clsSubClassB" ) then return new clsSubClassB() else if ( name = "clsSubClassC" ) then return new clsSubClassC() else 'それ以外の場合、例外を投げるか nothing を返すか end if end function end class 文字列ではなく列挙体としてもよいかもしれませんね。 定数であることには変わりはありませんが。 public enum CalculationMode Unknown = 0, clsSubClassA = 1, clsSubClassB = 2, clsSubClassC = 3, end enum public function CreateCalculator(mode as CalculationMode) as clsSuperClass switch ( mode ) case CalculationMode.clsSubClassA: return new clsSubClassA() case CalculationMode.clsSubClassB: return new clsSubClassB() case CalculationMode.clsSubClassC: return new clsSubClassC() default: 'それ以外の場合、例外を投げるか nothing を返すか end switch ※ VB.NET って select case だったかも。。 個人的には if の羅列が随時増えていくのはあまり好きではないので、 public class CalcuratorFactory public sub New() AddDefaultActivators() end sub private sub AddDefaultActivators() AddActivator(new SubClassAActivator()) AddActivator(new SubClassBActivator()) AddActivator(new SubClassCActivator()) end sub 'アクティベーターを登録 public sub AddActivator(activator as ICalcuratorActivator) m_Activators.Add(activator.GetKey(), activator) end sub private m_Activators as HashTable '.NET2.0 ならジェネリックリスト '指定されたキーに対応する計算処理インスタンスを返す public function CreateCalculator(key as string) as clsSuperClass if ( m_Activators.ContainsKey(key) ) then return DirectCast(m_Activators(key) as ICalcuratorActivator).Activate() else 'それ以外の場合、例外を投げるか nothing を返すか end if end function end class public interface ICalcuratorActivator '計算処理を一意に識別するキーを取得します。 function GetKey() as string '計算処理インスタンスを生成します。 function Activate() as clsSuperClass end interface で、アクティベーターを個々に作っていきます。 public class SubClassAActivator implements ICalcuratorActivator '計算処理を一意に識別するキーを取得します。 public function GetKey() as string return "clsSubClassA" end function '計算処理インスタンスを生成します。 function Activate() as clsSuperClass return new clsSubClassA() end function end class プログラムコードではこんな感じ dim factory as CalcuratorFactory = new CalcuratorFactory() dim calcrator as clsSuperClass = factory.CreateCalculator("clsCubClassA") [ メッセージ編集済み 編集者: masa 編集日時 2007-05-09 21:05 ] [ メッセージ編集済み 編集者: masa 編集日時 2007-05-09 21:06 ] | ||||||||||||||||||||
|
投稿日時: 2007-05-09 21:44
とか?(VB.NET って、こんなだっけ?) うげ。。。同じだった。Shared だっけ?C# でいう static つけるってことで。 [ メッセージ編集済み 編集者: Jitta 編集日時 2007-05-09 21:48 ] | ||||||||||||||||||||
|
投稿日時: 2007-05-09 23:15
赤ペン先生。
Select Case
Case Else
End Select 本題の方ですが、現状の状態であれば変更が予定されていても、 リフレクションではなくコンパイル解決が図れる方法が望ましいと思います。 ポリモーフィズム (インターフェイスの型でロジックを書く) とか、Command パターンとか。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||||||||||
|
投稿日時: 2007-05-09 23:28
同意です。
入力元がVB.NETのコードなら同意ですが、今回はDBから取得した文字列ということですので、 列挙体にする必要はないと思います。
Jittaさんが書いてらっしゃるように、Select CaseはStringに対しても使えますよ。
ファクトリパターンに従うのなら、clsSuperClassの静的メソッドにするのではなく、 別途ファクトリクラスを作った方が良いのではないでしょうか? いずれにしろ、DBに登録する文字列が必ずしもクラス名でなくて良くなるので、 DBテーブルのカラムサイズを小さくできるとか、 より分かりやすいキーを使えるなどのメリットもあると思います。 | ||||||||||||||||||||
|
投稿日時: 2007-05-10 01:14
もし、クラス名をDBに格納するという案を考えている段階であれば、 列挙体を定義してそれを数値化した値をDBに格納する手もあるかな、と。 文字列はあくまでも文字列ですが、 列挙体にすれば「計算処理を表す値」である保証ができます。 列挙値を追加した場合、列挙体を含むアセンブリをリビルドしなおす必要はありますが、 計算処理クラスも同じアセンブリに定義するとすればこれも問題にはならないですし。
個人的には case がたくさん続くのもあまり好きではないですね。 計算処理インスタンスの生成が単純にコンストラクタを呼べば終わり、 とならないものも出てくるかもしれません。 ところで、さとるさん。 スーパークラスの代わりにインターフェースを使って汎用化してはいかがでしょうか。 ICalcrator インターフェース 計算処理に必要な最低限のメソッド・プロパティを定義 ↑ ( implements ) | clsSuperClass クラス ↑ ( inherits ) | clsSubClassA クラス clsSubClassB クラス clsSubClassC クラス CreateCalcrator のようなメソッドからは ICalcrator を返すようにします。 各アプリケーションコードで汎用的に扱う点においては、 ICalcrator も clsSuperClass もそれほど変わりません。 dim calcrator as ICalcrator = factory.CreateCalcrator("キー") calcrator.Calcrate(引数) 処理が複雑になってしまっているそうですが、 いろいろな計算処理のロジックを clsSuperClass に詰め込んでいたりするのが原因でしたら、 インターフェースを基底にすることですっきりするかもしれません。 clsSuperClass を継承していなくてもよくなりますから、 別のスーパークラスを用意することも可能になります。 例えば複数の計算処理を順番に実行する計算処理クラスのような、 全く実装のことなる計算処理も作りやすいです。 public class MultiCalcrator implements ICalcrator public sub new(calcrators as ICalcrator()) if ( not calcrators is nothing ) then m_Calcrators = Directcast(m_Calcrators.Clone(), ICalcrator()) end if end sub private m_Calcrators as ICalcrator() '計算処理 public function calc(result as clsCalcResultClass) as boolean implements ICalcrator.calc if ( m_Calcrators == null ) then '例外をスロー、または何もせずに false を返すなど end if dim ret as boolean = true for i as integer = 0 to m_Calcrators.Length - 1 if ( not m_Calcrators(i).calc(result) ) then if ( ret ) then ret = false end if next return ret end function end class [ メッセージ編集済み 編集者: masa 編集日時 2007-05-10 01:16 ] | ||||||||||||||||||||
|
投稿日時: 2007-05-10 01:55
の部分についてだけですが、Enum.Parseメソッドを使用する方法もあります。 この方法であれば、データベースには文字列で登録でき、プログラムでは列挙型を使用できます。
| ||||||||||||||||||||
|
投稿日時: 2007-05-14 22:03
すみません、デザイン パターンは便利だと思う一方で、何で?と思うこともあります。 ここで、別途ファクトリ クラスを作ることの利便性を教えてください。 一応、検索<google.com>してみましたが、ファクトリ クラスをなぜ分けるのか、説明されているものに行き当たりませんでした。 唯一?ITpro の連載<nikkeibp.co.jp>で、次のように書いてありました。
なるほど、一緒に使う必要があるオブジェクトを作成する為というのは肯けます。 しかし、このスレッドのお題では一緒に使う必要があるオブジェクトは存在しません。よって、別のクラスにするメリットはないと思います。 また、同じページの最後の言葉も気になります。
確かに、GoFパターンは、多くの事例を研究して取り出したパターンではあるでしょう。しかし、この言葉通り、示されている通りである必要は無いと思います。 現に検索結果には、このような言葉もあります。
このようなわけで、別のクラスを作成する必要を感じません。ですので、「別途ファクトリクラスを作った方が良いのでは」とお考えになる理由を教えてください。 私が考えている、GoF パターンにしたがわないことによるメリットを挙げます。 * 使用するクラスが少なくなり、クラス図の見通しが良くなる。 * clsSuperClass を継承したものであることがわかりやすい。 * GoF パターンではファクトリ クラスのインスタンスを生成し、さらに作りたいオブジェクトを生成している。これにより、オブジェクト生成の時間が1回余分にかかる。 * 関連して、検索結果のページで挙げられている例では、ファクトリ クラスのオブジェクトは、本当に必要なオブジェクトを生成するためにのみ必要でその前後では不要である。また、本当に必要なオブジェクトを生成するためにファクトリをインスタンス化する必要もなさそう。 クラス図描いたの忘れてた。 [ メッセージ編集済み 編集者: Jitta 編集日時 2007-05-14 22:12 ] [ メッセージ編集済み 編集者: Jitta 編集日時 2007-05-14 22:13 ] |