web-dev-qa-db-ja.com

インターフェイスのサブクラスにToStringを実装させる

インターフェースIFooがあり、IFooのすべてのサブクラスでオブジェクトのToStringメソッドをオーバーライドするとします。これは可能ですか?

そのため、メソッド署名をIFooに追加するだけでは機能しません。

interface IFoo
{
    String ToString();
}

すべてのサブクラスがObjectを拡張し、その方法で実装を提供するため、コンパイラーはそれについて文句を言いません。助言がありますか?

57
rjohnston

あなたがインターフェイスでそれを行うことができるとは思わない。ただし、抽象基本クラスを使用できます。

public abstract class Base
{
    public abstract override string ToString(); 
}
84
Jon Skeet
abstract class Foo
{
    public override abstract string ToString();
}

class Bar : Foo
{
    // need to override ToString()
}
21
Andrew Peters

Jon&Andrew:その抽象的なトリックは本当に便利です。あなたがそれを抽象的であると宣言することによって連鎖を終わらせることができるとは思いもしませんでした。乾杯:)

これまで、派生クラスでToString()をオーバーライドする必要があったときは、常に次のようなパターンを使用しました。

public abstract class BaseClass
{
    public abstract string ToStringImpl();

    public override string ToString()
    {
        return ToStringImpl();
    }    
}
8
Mark Simpson

これであなたの質問に答えられないことはわかっていますが、あなたが求めていることをする方法がないので、私は他の人に見てもらうために私自身のアプローチを共有したいと思いました。

MarkとAndrewが提案したソリューションのハイブリッドを使用します。

私のアプリケーションでは、すべてのドメインエンティティは抽象基本クラスから派生しています。

public abstract class Entity
{
    /// <summary>
    /// Returns a <see cref="System.String"/> that represents this instance.
    /// </summary>
    public override string ToString()
    {
        return this is IHasDescription
                   ? ((IHasDescription) this).EntityDescription
                   : base.ToString();
    }
}

インターフェース自体は単純なアクセサーのみを定義します。

public interface IHasDescription : IEntity
{
    /// <summary>
    /// Creates a description (in english) of the Entity.
    /// </summary>
    string EntityDescription { get; }
}

つまり、フォールバックメカニズムが組み込まれています。つまり、Entityを実装するIHasDescriptionEntityDescriptionを提供する必要がありますが、Entityはそれでも文字列に変換します。

これがここで提案されている他のソリューションと根本的に異なるわけではないことを知っていますが、基本のEntityタイプの責任を最小限に抑えて、説明インターフェイスの実装をオプションのままにするというアイデアが好きですが、インターフェイスを実装している場合は、descriptionメソッドを実際に実装します。

IMHO、object基本クラスによって実装されるインターフェースは、実装として「カウント」されるべきではありません-そのためのコンパイラー・オプションがあればいいのですが、まあ...

1
mindplay.dk

インターフェイスメソッドを実装すると、メソッドが暗黙的にシールされます(オーバーライドもされます)。したがって、特に指示がない限り、インターフェイスの最初の実装はC#のオーバーライドチェーンを終了します。

必須.NET

抽象クラス=あなたの友達

チェック この質問

1
Ric Tokyo

特に私たちの親愛なる@ jon-skeet すでに彼自身の答えを提供した として、墓からこの古いスレッドを埋めて申し訳ありません。

しかし、抽象クラスを使用せずにインターフェイスを保持したい場合は、インターフェイスに System.IFormattable インターフェイスを実装するだけで、これはまだ可能だと思います。

_interface IFoo : IFormattable
{
}
_

留意すべき唯一のことは、このIFormattableを適切に実装するには、具体的な実装でObject.ToString()も上書きする必要があることです。

これはこのニースの投稿で明確に説明されています。

あなたの具体的なクラスは今のようです

_public class Bar : IFoo
{
    public string ToString(string format, IFormatProvider formatProvider)
    {
        return $"{nameof(Bar)}";
    }

    public override string ToString()
    {
        return ToString(null, System.Globalization.CultureInfo.CurrentCulture);
    }
}
_

これがまだ誰にも役立つことを願っています。

0
Seb T.

これらのメソッドが抽象的でない限り、サブクラスに強制的にoverrideベースクラスの仮想メソッドを強制することはできないと思います。

0