🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

482閲覧

抽象クラスを継承したクラスを個体識別番号で呼び出したい

gamu

総合スコア31

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2019/12/05 08:19

ある抽象クラスの計算メソッドを利用するクラスがあります。
仮にFruitsを継承した
Apple,Mango,Bananaとします。

個体識別用にMyNumberを与えております。

フルーツごとに計算式が異なります。

さて、識別番号だけがわかっている時に適当なクラスのインスタンスを紐付けてCulcメソッドを利用したいのですが、そういった事は可能なんでしょうか。
ちなみにフルーツは500種類ぐらいあります。
手作業で紐付けるのが泥臭い気がしたので質問させていただきました。

下記のhogeメソッドはどのように実装すればよいでしょうか。

ご回答よろしくおねがいいたします。

C#

1 2using System; 3using System.Collections.Generic; 4using System.Linq; 5using System.Text; 6using System.Threading.Tasks; 7 8 9 10public abstract class Fruits 11{ 12 public virtual int MyNumber { get; } 13 public abstract int Culc(int a, int b); 14} 15 16public class Apple : Fruits 17{ 18 public override int MyNumber => 1; 19 public override int Culc(int a , int b) 20 { 21 return a+b; 22 } 23} 24 25public class Mango : Fruits 26{ 27 public override int MyNumber => 2; 28 public override int Culc(int a, int b) 29 { 30 return a - b * b; 31 } 32} 33 34public class Banana : Fruits 35{ 36 public override int MyNumber => 3; 37 public override int Culc(int a, int b) 38 { 39 return a / b * 444; 40 } 41} 42 43 44 45class MainClass 46{ 47 48 static void Main() 49 { 50 int whatIwant = 2; 51 //Fruits someFruits = hoge(whatIWant); 52 //ここをどうすればよいのかわかりません 53//私はMangoのCulcを利用したい。 54 } 55 56}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

直接的な質問の答えではないのですが、識別番号とフルーツの紐づけ方に設計上のミスがあるのではないかと思います。

■問題1:設計上番号が重複する可能性がある。
Fruitsの継承クラス(Apple, Mango, Banana)は相互のMyNumberを知りません、設計上番号が重複する可能性があります。
■問題2:変更時に番号の振り直しが大変
例えばAppleの次にPearを追加したくなったとき500以上のクラスに分かれて書かれた番号を1つずつずらして書く必要が出てきます。
MyNumberはインスタンスではなくクラスの識別番号なので、別にプロパティとして持たせる必要もなく、別途これを定義・管理するのが吉かと思います。

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6 7public abstract class Fruits 8{ 9 // 動的に変更することがないものとして 10 public static readonly IReadOnlyDictionary<int, Type> FruitsTypeDictionary = 11 new Dictionary<int, Type> 12 { 13 { 1, typeof(Apple) }, 14 { 2, typeof(Mango) }, 15 { 3, typeof(Banana) }, 16 }; 17 public static Fruits CreateInstance(int number) 18 => Activator.CreateInstance(FruitsTypeDictionary[number]) as Fruits; 19 public abstract int Culc(int a, int b); 20} 21 22public class Apple : Fruits 23{ 24 public override int Culc(int a, int b) => a + b; 25} 26 27public class Mango : Fruits 28{ 29 public override int Culc(int a, int b) => a - b * b; 30} 31 32public class Banana : Fruits 33{ 34 public override int Culc(int a, int b) => a / b * 444; 35} 36 37class MainClass 38{ 39 static void Main() 40 { 41 int whatIwant = 2; 42 var someFruits = Fruits.CreateInstance(whatIwant); 43 Console.WriteLine(someFruits.Culc(10, 20)); 44 Console.ReadKey(); 45 } 46}

更に言えば質問内容を見る限りCalcは何のフィールドも参照しておらず、やろうとしていることを見ても、「whatIwantから新たにインスタンスを生成してCalcを選択的に利用する」というように見えるので、もしかしたら抽象クラスを継承するという構造自体不要かもしれません。

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6 7public enum Fruits 8{ 9 Apple = 1, 10 Mango = 2, 11 Banana = 3, 12} 13 14public static class FruitsCalculator 15{ 16 // 行き場がないのでstaticにするが、しかるべきところがあればそこに。 17 public static int Calc(Fruits fruits, int a, int b) 18 { 19 switch (fruits) 20 { 21 case Fruits.Apple: 22 return a + b; 23 case Fruits.Mango: 24 return a - b * b; 25 case Fruits.Banana: 26 return a / b * 444; 27 default: 28 throw new ArgumentException("Undifined fruits.", nameof(fruits)); 29 } 30 } 31} 32 33class MainClass 34{ 35 36 static void Main() 37 { 38 int value = FruitsCalculator.Calc((Fruits)2, 10, 20); 39 Console.WriteLine(value); 40 Console.ReadKey(); 41 } 42}

課題の背景が分からないので見当違いだったら申し訳ございません。

投稿2019/12/05 11:33

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gamu

2019/12/05 14:22

回答ありがとうございます。 >>別途これを定義・管理するのが吉かと思います。 やはりそうですか >>もしかしたら抽象クラスを継承するという構造自体不要 本当ですね。なぜか抽象クラスで行くことに決めてしまった。 インスタンスなど必要ないですね。 シンプルな仕様に変更できそうです。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2019/12/06 08:48

今回は背景が分からないのでstaticメソッドにしましたが、Utilityクラス(staticメソッドばかり集めた便利クラス)は何かと問題になることがございますので、どこか適切な行き先があればそちらのクラスのメンバとして実装してあげてくださいb
guest

0

手動でやったほうが良いとは思いますが、一応回答例を載せておきます。

流れとしては
アセンブリ内のすべての型を取得する

型・インスタンスが派生クラスかどうかを調べる

Type からインスタンスを生成する

という感じでやっています。

何度も検索をするのであれば、一度だけDictionary<Int, Fruits>などを生成しておいて、使いまわしたほうがいいです。

csharp

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6 7namespace ConsoleApplication1 8{ 9 public abstract class Fruits 10 { 11 public virtual int MyNumber { get; } 12 public abstract int Culc(int a, int b); 13 } 14 15 public class Apple : Fruits 16 { 17 public override int MyNumber => 1; 18 public override int Culc(int a, int b) 19 { 20 return a + b; 21 } 22 } 23 24 public class Mango : Fruits 25 { 26 public override int MyNumber => 2; 27 public override int Culc(int a, int b) 28 { 29 return a - b * b; 30 } 31 } 32 33 public class Banana : Fruits 34 { 35 public override int MyNumber => 3; 36 public override int Culc(int a, int b) 37 { 38 return a / b * 444; 39 } 40 } 41 42 43 class Program 44 { 45 static void Main(string[] args) 46 { 47 // 全クラス列挙 48 foreach (var type in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()) 49 { 50 // Fruitsのサブクラスだけ抽出 51 if (type.IsSubclassOf(typeof(Fruits))) 52 { 53 var fruits = (Fruits)Activator.CreateInstance(type); // インスタンス化 54 55 if (fruits.MyNumber == 2) 56 { 57 Console.WriteLine($"calc={fruits.Culc(123, 456)}"); 58 } 59 60 } 61 } 62 } 63 } 64} 65

投稿2019/12/05 08:42

takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gamu

2019/12/05 14:10

回答ありがとうございます。 dobonさんにも掲載されていたのですね。 勉強不足でした。 参考になりました。 やはりこの仕様で行くしか無いのなら手動でやるのが吉と言えそうですね。 しかし重複の心配が拭えないので検討し直そうと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問