簡體   English   中英

實現接口擴展屬性(繼承?)

[英]Implementing Interface Extending Properties (inheritance?)

我有一個必須解決的接口實現:這是一個示例:

interface ISettingsBase
{
    string Name { get; set;}
    DateTime TimeStamp { get; set; }
}

public class SettingsBase : ISettingsBase
{
    public string Name { get; set; }
    public DateTime TimeStamp { get; set; }
}

interface IWorkerBase
{
    ISettingsBase Settings { get; set; }
}

public class WorkerBase: ISettingsBase
{
    public ISettingsBase Settings { get; set; }
}

interface IExtendedSettings : ISettingsBase
{
    string FilePath { get; set; }
}

interface IWorkerExtended : IWorkerBase
{
    // This configuration property should respect those of
    // the IWorkerBase and increase the features.
    IExtendedSettings Settings { get; set; }
}

public class WorkerExtended : WorkerBase, IWorkerExtended
{
    ...
    ...
    public IExtendedSettings Settings { get; set; }
}

問題是編譯器告訴我WorkerExtended中存在錯誤,並且我不尊重IWorkerBase.Settings接口的實現。 問題是我需要新的改進類還支持具有更多屬性的配置。

interface IWorkerBase
{
    ISettingsBase Settings { get; set; }
}

interface IWorkerExtended : IWorkerBase
{
    IExtendedSettings Settings { get; set; }
}

這已經成為問題,因為IWorkerExtended.Settings隱藏 IWorkerBase所需的Settings成員。 因此, IWorkerExtended實現者仍將必須提供原始的Settings成員(類型為ISettingsBase ),以可傳遞地實現IWorkerBase

編譯器會在這里警告您,因為此成員隱藏正在進行。 通常這樣做是錯誤的,因此您需要使用new鍵盤來表示您願意這樣做:

interface IWorkerExtended : IWorkerBase
{
    new IExtendedSettings Settings { get; set; }
}

注意,這對實現者沒有影響。 因此,在實現該接口時,您將必須提供兩個Settings成員。 您可以通過顯式實現基本接口來做到這一點:

public class Worker : IWorkerExtended
{
    public IExtendedSettings Settings { get; set; }

    ISettingsBase IWorkerBase.Settings { get; set; }
}

這樣做的原因是很簡單: 里氏替換原則說,當IWorkerExtended是的一個亞型IWorkerBase ,然后類型的任何對象IWorkerBase可以通過類型的對象替換IWorkerExtended 現在考慮一下:

IWorkerBase baseWorker = GetExtendedWorker();
baseWorker.Settings = new SettingsBase(); // not extended

這只會工作,如果你可以在指定SettingsBaseSettings這是什么類型IWorkerBase擔保(因為SettingsBase是一個亞型ISettingsBase )。 因此,為了使擴展工作程序可分配給基本工作程序類型,需要確保可以ISettingsBase設置ISettingsBase 但是,如果只實施IWorkerExtended ,則可以將更具體的擴展設置分配給Settings

接口旨在隱藏實現細節,而不是告訴消費者“哦,這個家伙還有些其他字段”。

通常,強制轉換或類型檢查(如if (worker is IWorkerExtended)表明您根本不需要接口。

我想說,在這種情況下,最好讓一堆worker類實現一個空的IWorker接口。

就像是:

public interface IWorker
{
}

public class SettingsBase
{
    public string Name { get; set; }
    public DateTime TimeStamp { get; set; }
}

public class ExtendedSettingsA : SettingsBase
{
    public string FilePath { get; set; }
}

public class ExtendedSettingsB : SettingsBase
{
    public string SomeOtherProp { get; set; }
}

public class WorkerBase : IWorker
{
    public SettingsBase Settings { get; set; }
}

public class WorkerExtendedA : IWorker
{
    public ExtendedSettingsA Settings { get; set; }
}

public class WorkerExtendedB : IWorker
{
    public ExtendedSettingsB Settings { get; set; }
}


public class XmlLoader
{
    public IWorker Load(string xml)
    {
        return null; // instance of WorkerBase or WorkerExtendedA or WorkerExtendedB
    }
}

public class Consumer
{
    public void Process(IWorker w)
    {
        if (w is WorkerBase)
        {
            WorkerBase wbase = w as WorkerBase;
            string name = wbase.Settings.Name;
            DateTime t = wbase.Settings.TimeStamp;
        }
        if (w is WorkerExtendedA)
        {
            WorkerExtendedA wa = w as WorkerExtendedA;
            string name = wa.Settings.Name;
            DateTime t = wa.Settings.TimeStamp;
            string f = wa.Settings.FilePath;
        }
        if (w is WorkerExtendedB)
        {
            WorkerExtendedB wb = w as WorkerExtendedB;
            string name = wb.Settings.Name;
            DateTime t = wb.Settings.TimeStamp;
            string other = wb.Settings.SomeOtherProp;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM