【问题标题】:implementing abstract classes vs interfaces [closed]实现抽象类与接口[关闭]
【发布时间】:2021-12-11 18:24:17
【问题描述】:

我不熟悉使用接口和抽象类。我正在与之合作的团队提出了他们所谓的基类的实现,该基类将由所有视图模型类实现。这是他们想出的:

public interface IBaseViewModel<T>
{
    #region public properties
    string Message { get; set; }
    string SaveType { get; set; }
    bool IsVisibleMessage { get; set; }
    bool IsVisibleDecision { get; set; }
    bool IsApiSuccess { get; set; }
    Guid EntityId { get; set; }
    string EntityQDSId { get; set; }
    string EntityType { get; set; }
    #endregion

    #region public methods
    Task Init();
    Task Init(Guid Id);
    Task<T> Create();
    Task<T> Get(Guid Id);
    Task<T> Get(string Id);
    Task<IEnumerable<T>> GetList(Guid Id);
    Task<IEnumerable<T>> GetList(string Id);
    Task<T> Insert(T t);
    Task<T> Update(Guid Id, T t);
    Task<T> Delete(Guid Id);
    void Dispose();
    #endregion
}

public abstract class BaseViewModel<T> : IBaseViewModel<T>, IDisposable
{
    public Guid EntityId { get; set; }
    public string EntityQDSId { get; set; }
    public string EntityType { get; set; }

    public string Message { get; set; }
    public string SaveType { get; set; }
    public bool IsVisibleMessage { get; set; }
    public bool IsVisibleDecision { get; set; }
    public bool IsApiSuccess { get; set; }

    public virtual Task Init()
    {
        return Task.FromResult<T>(default);
    }

    public virtual Task Init(Guid Id)
    {
        return Task.FromResult<T>(default);
    }

    public virtual Task<T> Create()
    {
        return Task.FromResult<T>(default);
    }

    public virtual Task<T> Get(Guid Id)
    {
        return Task.FromResult<T>(default);
    }

    public virtual Task<T> Get(string Id)
    {
        return Task.FromResult<T>(default);
    }

    public virtual Task<IEnumerable<T>> GetList(Guid Id)
    {
        return Task.FromResult<IEnumerable<T>>(default);
    }

    public virtual Task<IEnumerable<T>> GetList(string Id)
    {
        return Task.FromResult<IEnumerable<T>>(default);
    }

    public virtual Task<IEnumerable<T>> GetForGrid(Guid Id)
    {
        return Task.FromResult<IEnumerable<T>>(default);
    }

    public virtual Task<T> Insert(T t)
    {
        return Task.FromResult<T>(default);
    }

    public virtual Task<T> Update(Guid Id, T t)
    {
        return Task.FromResult<T>(default);
    }

    public virtual Task<T> Delete(Guid Id)
    {
        return Task.FromResult<T>(default);
    }

    public virtual void ProcessDto(T t)
    {
    }

    public virtual void Dispose()
    {
    }
}

下面是实现:

      public interface IAccountBillViewModel<T> : IBaseViewModel<AccountBillGroup>
{

}

public class AccountBillViewModel<T> : BaseViewModel<AccountBillGroup>, IAccountBillViewModel<AccountBillGroup>
{

}

在研究这个问题时,我发现了几个像下面这样的 cmets

https://stackoverflow.com/a/479154 [@Alex][1]

我的观点:

  1. 既然抽象类中只有代码签名,没有任何代码的实现,而且可以从多个接口继承,为什么要使用抽象类而不是接口?
  2. 继承槽将保持打开状态,以防我们将来想从另一个类继承。

他们的观点:

  1. 属性只需要在基类中实现,这些属性将在所有实现中可用,无需再次声明属性。
  2. 只有那些需要在实现中使用的方法才需要被覆盖。如果使用接口,则必须在每个实现中实现所有方法。

当没有实现,只有方法签名时,选择抽象基类是否有价值?

【问题讨论】:

  • 补充你的观点,并从他们的观点中减去:docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/…
  • 在这种情况下,您不太可能需要从另一个类继承。更有可能的是,您需要一个共同的基类来实现共享行为。
  • 在接口和 ABC(抽象基类)之间进行选择时要考虑的另一件事是版本控制。如果向已发布的接口添加方法,它将破坏实现该接口的每个类 - 但您可以向 ABC 添加(非抽象)方法,而不会破坏从 ABC 派生的任何内容。
  • 我觉得这个问题更适合codereview.stackexchange.com

标签: c# interface abstract-class


【解决方案1】:

我更喜欢使用接口,因为类可以实现多个接口。

当您有一些可以在继承类中重用的默认行为时,抽象类更有意义。

【讨论】:

    猜你喜欢
    • 2012-07-17
    • 2012-01-20
    • 1970-01-01
    • 2018-04-05
    • 2014-08-18
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    • 2018-12-16
    相关资源
    最近更新 更多