9

抽象クラスと、保護されたコンストラクターのみを持つクラスのすべての違いは何ですか?どちらもインスタンス化できないという点で、私とよく似ているようです。

編集:

保護されたコンストラクターを持つ基本クラスを使用して、派生クラスにインスタンスをどのように作成しますか?例えば:

public class ProtectedConstructor
{
    protected ProtectedConstructor()
    {

    }

    public static ProtectedConstructor GetInstance()
    {
        return new ProtectedConstructor(); // this is fine
    }
}

public class DerivedClass : ProtectedConstructor
{

    public void createInstance()
    {
        ProtectedConstructor p = new ProtectedConstructor(); // doesn't compile
    }

    public static ProtectedConstructor getInstance()
    {
        return new ProtectedConstructor(); // doesn't compile

    }
}
4

9 に答える 9

12

静的コンストラクターまたは静的メソッドで、クラス自体の中から保護されたコンストラクターを使用してクラスをインスタンス化できます。これは、シングルトンまたはファクトリタイプのものを実装するために使用できます。

抽象クラスはまったくインスタンス化できません。その目的は、1つ以上の子クラスが実装を完了し、それらのクラスがインスタンス化されることです。

編集:

ProtectedConstructor.GetInstance();の代わりに呼び出すとnew ProtectedConstructor();、機能します。たぶん、保護されたコンストラクターはこのように呼び出すことはできませんか?しかし、保護されたメソッドは確かに可能です。

これは、このトピックに関する興味深い記事です。

于 2010-02-05T19:45:32.340 に答える
3

ほとんどの場合、どちらもサブクラスを介してのみ生成できるため、実際的な違いはほとんどありません。

ただし、クラスにマークを付けることにabstractは2つの利点があります。

  1. 保護されたコンストラクターを使用すると、2つの方法でクラスのインスタンスを作成できます。BindingFlags.NonPublicでActivator.CreateInstanceを使用するか、クラス(またはサブクラス)で定義されたファクトリメソッドを使用してクラスのインスタンスを作成できます。ただし、abstractとマークされたクラスは作成できません。

  2. クラスにマークを付けることで、意図をより明確にしていますabstract。個人的には、これが最も説得力のある理由だと思います。

于 2010-02-05T19:46:20.837 に答える
1

他の人が言及していなかったことを考慮すべきもう一つのことは、あなたのコードが将来維持されるかもしれないということです。メンテナがパブリックコンストラクタをクラスに追加すると、インスタンス化できます。これはあなたのデザインを壊すかもしれないので、あなたはそれ(またはそれに対応するためのデザイン)を防ぐべきです。

他の人がこの種の変更を行うのを防ぐために、コードにコメントを付けることができます。または、他の人が言ったように、「要約」を使用して、意図を明示的に文書化します。

于 2010-02-05T21:17:07.287 に答える
1

外部のブラックボックスの観点からは、どちらもインスタンス化できないという点で似ています。ただし、抽象クラスをインスタンス化することはできません。抽象クラスでは、クラス自体の中から、または継承者から、保護されたコンストラクターのみを使用してクラスを構築できます。

于 2010-02-05T19:45:52.943 に答える
1

抽象クラスは抽象メソッドを持つことができます。子クラスが実装する必要のある、メソッドシグネチャのみで構成され、本体は含まれないメソッド。

真剣に、まだ一人もそれについて言及していませんか?

于 2010-02-05T20:23:17.537 に答える
1

getInstanceの場合、ProtectedConstructorクラスを作成し、それをDerivedClassとしてダウンキャストすることを期待しているため、この例には欠陥があります。代わりに、派生クラスにコンストラクターがある、もう少し完全な実装が必要です。

public class ProtectedConstructor
{
    protected ProtectedConstructor(string arg)
    {
        // do something with arg
    }

    public static ProtectedConstructor GetInstance()
    {
        return new ProtectedConstructor("test"); 
    }
} 

public class DerivedClass : ProtectedConstructor
{
    protected DerivedClass(string arg) : base(arg)
    {
    }

    public void createInstance()
    {
        DerivedClass p = new DerivedClass("test"); 
    }

    public static DerivedClass getInstance()
    {
        return new DerivedClass("test"); 
    }
}

抽象クラスの主な違いは、サブクラスが実装する必要がある抽象メソッドを定義することですが、デフォルトの実装を提供する必要はありません。たとえば、Runメソッドを持つある種のThreadクラスがあるとします。Runを呼び出すたびに、最初にログを設定し、次にスレッドの実際の作業を実行してから、ログを停止するようにします。次のような抽象Threadクラスを作成できます。

public abstract Thread
{
    protected Thread()
    {
    }

    public void Run()
    {
        LogStart();
        DoRun();
        LogEnd();
    }

    protected abstract DoRun();

    private void LogStart()
    {
         Console.Write("Starting Thread Run");
    }

    private void LogEnd()
    {
         Console.Write("Ending Thread Run");
    }
}


public class HelloWorldThread : Thread
{
    public HelloWorldThread()
    {
    }

    protected override DoRun()
    {
        Console.Write("Hello World");
    }
}
于 2010-02-05T20:33:04.247 に答える
0

頭に浮かぶ最初の違いは、抽象クラスはインスタンス化できないということですが、保護されたコンストラクターを持つクラスは、別のパブリックメソッドをスローしてインスタンス化できます。

この一般的な例は、シングルトンパターンのようなものです:http://en.wikipedia.org/wiki/Singleton_pattern

于 2010-02-05T19:48:25.723 に答える
0

別の抽象クラスから抽象クラスを継承する場合、抽象メソッドを満たす必要はありませんが、保護されたctorを持つ通常のクラスを使用します。例


public abstract class Parent
{
  protected abstract void AMethod();
}

public abstract class Child: Parent
{
  // does not implement AMethod, and that's ok
}

public class Child2: Parent
{
  // does not implement AMethod, and that will cause a compile error
}

于 2010-02-05T20:03:22.113 に答える
0

クラスの静的使用のみを許可する(つまり、純粋な基本クラスとして使用しない)場合は、代わりにstaticキーワードを使用する必要があります。CLRは、Reflection(AFAIK)を含む任意のメソッドを介してクラスのインスタンスが作成されるのを防ぎます。

于 2010-02-05T20:24:47.537 に答える