5

作成した抽象クラスから継承するクラスのコレクションがあります。抽象クラスの具体的な実装のインスタンスを作成するためのファクトリとして抽象クラスを使用したいと思います。

親クラスを除くすべてのコードからコンストラクターを非表示にする方法はありますか?

基本的にはこうしたい

public abstract class AbstractClass
{
    public static AbstractClass MakeAbstractClass(string args)
    {
        if (args == "a")
            return new ConcreteClassA();
        if (args == "b")
            return new ConcreteClassB();
    }
}

public class ConcreteClassA : AbstractClass
{
}

public class ConcreteClassB : AbstractClass
{
}

しかし、私は誰もが 2 つの具象クラスを直接インスタンス化できないようにしたいと考えています。MakeAbstractClass() メソッドだけが基本クラスをインスタンス化できるようにしたいと考えています。これを行う方法はありますか?

UPDATE
Abstract クラスの外部から ConcreteClassA または B の特定のメソッドにアクセスする必要はありません。Abstract クラスが提供する public メソッドだけが必要です。具体的なクラスがインスタンス化されるのを防ぐ必要はありません。抽象クラスの内部にあるいくつかの非常に具体的なものの実装が異なるだけで、新しいパブリック インターフェイスは提供されないため、回避しようとしているだけです。

私にとって、最も簡単な解決策は、samjudson が述べたように子クラスを作成することです。ただし、抽象クラスのファイルが必要以上に大きくなるため、これは避けたいと思います。組織のために、クラスをいくつかのファイルに分割しておきたいと思います。

これは簡単に解決できるものではないと思います...

4

9 に答える 9

6

私にとって、最も簡単な解決策は、samjudson が述べたように子クラスを作成することです。ただし、抽象クラスのファイルが必要以上に大きくなるため、これは避けたいと思います。組織のために、クラスをいくつかのファイルに分割しておきたいと思います。

問題ありません。partialキーワードを使用するだけで、内部クラスを必要な数のファイルに分割できます。同じファイルに保存する必要はありません。

以前の回答:

可能ですが、リフレクションのみ

public abstract class AbstractClass
{
    public static AbstractClass MakeAbstractClass(string args)
    {
        if (args == "a")
            return (AbstractClass)Activator.CreateInstance(typeof(ConcreteClassA), true);
        if (args == "b")
            return (AbstractClass)Activator.CreateInstance(typeof(ConcreteClassB), true);
    }
}

public class ConcreteClassA : AbstractClass
{
    private ConcreteClassA()
    {
    }
}

public class ConcreteClassB : AbstractClass
{
    private ConcreteClassB()
    {
    }
}

そして、醜いMakeAbstractClass(string args)のない別のパターンがあります

public abstract class AbstractClass<T> where T : AbstractClass<T>
{
    public static T MakeAbstractClass()
    {
        T value = (T)Activator.CreateInstance(typeof(T), true);
        // your processing logic
        return value;
    }
}

public class ConcreteClassA : AbstractClass<ConcreteClassA>
{
    private ConcreteClassA()
    {
    }
}

public class ConcreteClassB : AbstractClass<ConcreteClassB>
{
    private ConcreteClassB()
    {
    }
}
于 2008-08-21T15:36:10.610 に答える
3

クラスが同じアセンブリにある場合、コンストラクターを内部にすることはできませんか?

于 2008-08-21T15:21:54.873 に答える
2

次のように、サブクラスを子クラスにすることができます。

public abstract class AbstractClass
{
    public static AbstractClass MakeAbstractClass(string args)
    {
        if (args == "a")
            return new ConcreteClassA();
        if (args == "b")
            return new ConcreteClassB();
    }

    private class ConcreteClassA : AbstractClass
    {
    }

    private class ConcreteClassB : AbstractClass
    {
    }
}

@Vaibhavこれは、クラスも非表示になっていることを意味します。しかし、これは、コンストラクターを完全に非表示にする唯一の方法であることがわかっている限りです。

編集:他の人が言及しているように、リフレクションを使用して同じことを達成できます。これは、実際にあなたが望むものに近いかもしれません-たとえば、上記のメソッドは、抽象クラスと同じファイル内にある具象クラスに応答します。これはおそらくあまり便利ではありません。この方法は優れた「ハック」であり、具体的なクラスの数と複雑さが少ない場合に適しています。

于 2008-08-21T15:15:20.647 に答える
1

受け入れられた回答に続いて、パブリックインターフェイスがあり、プライベートクラスにインターフェイスを実装させた場合、インターフェイスへのポインタを返すことができ、親の抽象クラスの外部の誰もがそれらを使用できます(子クラスを非表示にしたまま) )。

于 2008-09-10T12:30:08.677 に答える
1

いいえ、それはできないと思います。

于 2008-08-21T15:15:00.333 に答える
0

このクラスを別のサービスアセンブリで使用している場合は、internalキーワードを使用できます。

public class AbstractClass
{
    public AbstractClass ClassFactory(string args)
    {
        switch (args)
        {
            case "A":
                return new ConcreteClassA();               
            case "B":
                return new ConcreteClassB();               
            default:
                return null;
        }
    }
}

public class ConcreteClassA : AbstractClass
{
    internal ConcreteClassA(){ }
}

public class ConcreteClassB : AbstractClass
{
    internal ConcreteClassB() {}
}
于 2008-08-23T16:21:15.293 に答える
0

partialクラスのコードを多くのファイルに分割するためのキーワードを使用できませんか?

于 2008-08-21T15:55:08.803 に答える
0

実際にこれを行う必要がありますか?真の設計ニーズがないのにある種の疑似ファクトリ パターンを使用している場合、コードの理解、維持、および拡張が難しくなるだけです。

これを行う必要がない場合は、真のファクトリ パターンを実装するだけです。または、より多くの ALTy、DI/IoC フレームワークを使用します。

于 2008-08-21T15:33:29.417 に答える
-2

あなたがする必要があるのは、デフォルトのコンストラクターが作成されるのを防ぐためにこれです。クラスが同じアセンブリにない場合、internal を public に変更できます。

public abstract class AbstractClass{

 public static AbstractClass MakeAbstractClass(string args)
 {
    if (args == "a")
        return ConcreteClassA().GetConcreteClassA();
    if (args == "b")
        return ConcreteClassB().GetConcreteClassB();
 }
}

public class ConcreteClassA : AbstractClass
{
  private ConcreteClassA(){}

  internal static ConcreteClassA GetConcreteClassA(){
       return ConcreteClassA();
  }
}

public class ConcreteClassB : AbstractClass
{
  private ConcreteClassB(){}
  internal static ConcreteClassB Get ConcreteClassB(){
       return ConcreteClassB();
  }

}
于 2008-08-21T15:40:20.803 に答える