web-dev-qa-db-ja.com

サブクラスにメソッドを強制的に実装する方法

オブジェクト構造を作成していますが、ベースのすべてのサブクラスにメソッドの実装を強制する必要があります。

私がそれを行うことを考えることができる唯一の方法は次のとおりでした:

  1. 抽象クラス-機能しますが、基本クラスにはいくつかのサブクラスで使用される便利なヘルパー関数があります。

  2. インターフェース-基本クラスのみに適用される場合、サブクラスは基本クラスのみが実行する機能を実装する必要はありません。

これも可能ですか?

N.B.これは.NET 2アプリです。

41
tgandrews

実装されている他のメソッドとともに、クラスに抽象メソッドを含めることができます。インターフェイスに対する利点は、クラスにコードを含めることができ、抽象メソッドの詳細を新しいオブジェクトに強制的に入力できることです。

public abstract class YourClass
{
    // Your class implementation

    public abstract void DoSomething(int x, int y);

    public void DoSomethingElse(int a, string b)
    {
        // You can implement this here
    }
}
60
Kelsey

インターフェース-基本クラスのみに適用される場合、サブクラスは基本クラスのみが実行する機能を実装する必要はありません。

これは完全に正しいわけではありません。基本クラスが抽象の場合、インターフェイスに属するメソッドを抽象としてマークし、サブクラスでの実装を強制できます。

それはあなたが言及しなかったオプションをもたらします:両方を使用すること。 IFooインターフェイスと、それを実装するFooBase抽象基本クラス、またはその一部があります。これにより、サブクラスにインターフェースの「デフォルト」実装(またはその一部)が提供されます。また、他の何かから継承してインターフェースを実装することもできます。例が役立ちます:

// Your interface
interface IFoo { void A(); void B; }

// A "default" implementation of that interface
abstract class FooBase : IFoo
{
    public abstract void A();

    public void B()
    {
        Console.WriteLine("B");
    }
}

// A class that implements IFoo by reusing FooBase partial implementation
class Foo : FooBase
{
    public override void A()
    {
        Console.WriteLine("A");
    }
}

// This is a different class you may want to inherit from
class Bar
{
    public void C()
    {
        Console.WriteLine("C");
    }
}

// A class that inherits from Bar and implements IFoo
class FooBar : Bar, IFoo
{
    public void A()
    {
        Console.WriteLine("Foobar.A");
    }
    public void B()
    {
        Console.WriteLine("Foobar.B");
    }
}
14

抽象クラス-動作しますが、基本クラスにはいくつかのサブクラスで使用される便利なヘルパー関数があります

抽象クラスは、提供するすべての関数を抽象にする必要はありません。

abstract class Base {
    public void Foo() {} // Ordinary method
    public virtual void Bar() {} // Can be overridden
    public abstract void Xyz(); // This one *must* be overridden
}

publicprotectedに置き換えた場合、マークされたメソッドはonlyになり、ベースクラスとサブクラスから見えることに注意してください。

11
Dario

はい、これを行う必要があるすべてのクラスが既存の抽象基本クラスの論理的なサブクラスである場合、基本クラスに抽象メソッドを追加します...これは、実装を後で追加できるため、インターフェイスよりも優れています(抽象基本クラスメソッドをデフォルト実装の仮想メソッドに変更することにより)、たとえば10個の派生クラスのうち8個が同じ実装を持ち、そのうちの2つだけが異なる場合.

編集:(以下のコメントのスレッドに基づいて)これを行うには、基本クラスを抽象として宣言する必要があります...非抽象クラスをインスタンス化できるため、非抽象クラスに抽象メソッドを含めることはできません。そのインスタンスが作成された場合、そのメソッドの実装はありません。これは違法です。ベースを抽象として宣言することにより、クラスのインスタンス化を禁止します。次に、非抽象derivedクラスのみをインスタンス化できます。ここで、(基本メソッドは抽象であるため)そのメソッドの実装を追加する必要があります。

6
Charles Bretana

また、params(.netcore 2.2)を含む完全なワーカーサンプル:

class User{
    public string Name = "Fen";
}

class Message{
    public string Text = "Ho";
}

// Interface
interface IWorkerLoop
{
    // Working with client message
    string MessageWorker(string msg);
}

// AbstractWorkerLoop partial implementation
public abstract class AbstractWorkerLoop : IWorkerLoop
{
    public User user;
    public Message msg;

    // Append session object to loop
    public abstract AbstractWorkerLoop(ref User user, ref Message msg){
        this.user = user;
        this.msg = msg;
    }

    public abstract string MessageWorker(string msg);
}

// Worker class
public class TestWorkerLoop : AbstractWorkerLoop
{
    public TestWorkerLoop(ref User user, ref Message msg) : base(user, msg){
        this.user = user;
        this.msg = msg;
    }

    public override string MessageWorker(string msg){
        // Do something with client message    
        return "Works";
    }
}
0
WorksIt