摘要 class 参考实现 classes

Abstract class reference implementation classes

我有以下摘要class:

public abstract class Period
{
    public int Id { get; set; }
    protected abstract DateTimeOffset StartDate { get; set; }
    protected abstract DateTimeOffset EndDate { get; set; }
}

实施如下:

public class MonthlyPeriod : Period
{
    private DateTimeOffset startDate { get; set; }

    public MonthlyPeriod(DateTimeOffset startDate)
    {
        this.startDate = startDate;
    }

    protected override DateTimeOffset EndDate
    {
        get
        {
            return startDate.AddMonths(1).AddTicks(-1);
        }

        set
        {
            startDate = new DateTime(value.Year, value.Month, 1);
        }
    }

    protected override DateTimeOffset StartDate
    {
        get
        {
            return startDate;
        }

        set
        {
            startDate = new DateTimeOffset(value.Year, value.Month, 1, 0, 0, 0, value.Offset);
        }
    }
}

我想做的是在摘要中包含以下抽象方法 class:

public abstract Period GetPreviousPeriod();
public abstract Period GetNextPeriod();

然后在实现中让它们 return MonthlyPeriod 特别是:

public override MonthlyPeriod GetNextPeriod() => new MonthlyPeriod(EndDate.AddDays(1));
public override MonthlyPeriod GetPreviousPeriod() => new MonthlyPeriod(StartDate.AddDays(-1));

然而,这有一个明显的缺陷,即我在摘要 class 中将方法的类型指定为 Period,而不是 MonthlyPeriod

是否有直接的方法来定义这种类型的关系?


到目前为止我得到的最佳解决方案是:

  1. 将抽象方法从 public 切换到 protected
  2. 根据需要使已实现的抽象方法产生 Period
  3. 在摘要中class定义以下方法:

    public T GetPreviousPeriod<T>() where T : Period
    {
        T prevPeriod = GetPreviousPeriod() as T;
        if (prevPeriod == null)
        {
            throw new ArgumentException();
        }
    
        return prevPeriod;
    }
    
    public T GetNextPeriod<T>() where T : Period
    {
        T nextPeriod = GetNextPeriod() as T;
        if (nextPeriod == null)
        {
            throw new ArgumentException();
        }
    
        return nextPeriod;
    }
    

这行得通;但是,它不一定是一个完整的解决方案。特别是它缺少类型正确的编译时承诺。

您可以定义一个像 IPeriod 这样的接口,并将其作为接口方法中的 return 类型。然后你的具体实现你可以 return MonthlyPeriod 这将实现接口 IPeriod

与其在基础 class 上强制使用该方法,不如创建一些扩展方法来创建这些新实例并 returns 它们呢?

此外,句点也用作 "PeriodFactory" 看起来不对,因为它违反了 S in SOLID

public static MonthlyPeriod GetNextPeriod(this MonthlyPeriod period)
{
    return new MonthlyPeriod(period.EndDate);
} 

想出了一个解决方案,适用于我原来的问题。

  1. Period更改为Period<T> where T : Period<T>
  2. public abstract Period GetPreviousPeriod();更改为public abstract T GetPreviousPeriod();
  3. GetNextPeriod() 重复 2。
  4. MonthlyPeriod : Period 更改为 MonthlyPeriod : Period<MonthlyPeriod>