C# 避免为接口 属性 重复代码
C# avoid repeating code for interface property
给定界面:
interface IVotable
{
int TotalUpvotes { get; }
int TotalDownvotes { get; }
int TotalVoteScore { get; }
}
实施:
public class Comment : IVotable
{
public int TotalUpvotes { get; private set; }
public int TotalDownvotes { get; private set; }
public int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1 ; } }
}
避免在每个 class 中以相同方式实施 TotalVoteScore
的最佳方法是什么?
如果你想要一个类似接口的东西(一个合同,说必须有一些方法具有指定的签名)结合通用代码,我想解决方案是一个抽象 class:
public abstract class Votable
{
public abstract int TotalUpvotes { get; protected set; }
public abstract int TotalDownvotes { get; protected set; }
public virtual int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1; } }
}
并从中得出 class:
public class Comment : Votable
{
public override int TotalUpvotes { get; protected set; }
public override int TotalDownvotes { get; protected set; }
}
public abstract class VotableBase
{
public int TotalUpvotes { get; protected set;}
public int TotalDownvotes { get; protected set; }
public int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1 ; } }
}
那么您的派生 class 不需要任何实现 - 它已经继承了属性:
public class Comment : VotableBase
{
public void DoThings()
{
//e.g.
Console.WriteLine(TotalVoteScore);
}
}
如果 TotalVoteScore
始终以相同的方式计算,您可以将其作为 IVotable
上的扩展方法:
public static int TotalVoteScore(this IVotable v) {
return v.TotalUpvotes - v.TotalDownvotes + 1
}
如果只是 TotalVoteScore
您不想重新实施,那么这就是要走的路:
public interface IVotable
{
int TotalUpvotes { get; }
int TotalDownvotes { get; }
int TotalVoteScore { get; }
}
public abstract class VotableBase : IVotable
{
public abstract int TotalUpvotes { get; protected set; }
public abstract int TotalDownvotes { get; protected set; }
public virtual int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1 ; } }
}
public class Comment : VotableBase
{
public override int TotalUpvotes { get; protected set; }
public override int TotalDownvotes { get; protected set; }
}
将构图方法融入其中。我一点也不反对继承。但这让我觉得这是一个不使用它的好例子。为什么要限制此 class 只能导出投票功能?我可以想象这个 class 有很多与 "Comment" 更密切相关的东西,例如作者信息(排名、个人简介、头像)、格式、年龄、编辑历史等。其中一些似乎可能更适合作为基础 class.
public interface IVotable
{
int TotalUpvotes { get; }
int TotalDownvotes { get; }
int TotalVoteScore { get; }
}
// shared implementation
public class VoteStatus : IVotable
{
public int TotalUpvotes { get; private set; }
public int TotalDownvotes { get; private set; }
public int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1; } }
}
// has A...
public class Comment : IVotable
{
// expose it?
public IVotable VoteStatus { get; private set; }
// allow current vote status to be injected?
public Comment(IVotable voteStatusReference)
{
this.VoteStatus = voteStatusReference;
}
// or don't use injection?
public Comment()
: this(new VoteStatus())
{
}
public int TotalUpvotes => this.VoteStatus.TotalUpvotes;
public int TotalDownvotes => this.VoteStatus.TotalDownvotes;
public int TotalVoteScore => this.VoteStatus.TotalVoteScore;
}
注意:我也觉得这里的扩展方法建议比继承要好。
给定界面:
interface IVotable
{
int TotalUpvotes { get; }
int TotalDownvotes { get; }
int TotalVoteScore { get; }
}
实施:
public class Comment : IVotable
{
public int TotalUpvotes { get; private set; }
public int TotalDownvotes { get; private set; }
public int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1 ; } }
}
避免在每个 class 中以相同方式实施 TotalVoteScore
的最佳方法是什么?
如果你想要一个类似接口的东西(一个合同,说必须有一些方法具有指定的签名)结合通用代码,我想解决方案是一个抽象 class:
public abstract class Votable
{
public abstract int TotalUpvotes { get; protected set; }
public abstract int TotalDownvotes { get; protected set; }
public virtual int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1; } }
}
并从中得出 class:
public class Comment : Votable
{
public override int TotalUpvotes { get; protected set; }
public override int TotalDownvotes { get; protected set; }
}
public abstract class VotableBase
{
public int TotalUpvotes { get; protected set;}
public int TotalDownvotes { get; protected set; }
public int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1 ; } }
}
那么您的派生 class 不需要任何实现 - 它已经继承了属性:
public class Comment : VotableBase
{
public void DoThings()
{
//e.g.
Console.WriteLine(TotalVoteScore);
}
}
如果 TotalVoteScore
始终以相同的方式计算,您可以将其作为 IVotable
上的扩展方法:
public static int TotalVoteScore(this IVotable v) {
return v.TotalUpvotes - v.TotalDownvotes + 1
}
如果只是 TotalVoteScore
您不想重新实施,那么这就是要走的路:
public interface IVotable
{
int TotalUpvotes { get; }
int TotalDownvotes { get; }
int TotalVoteScore { get; }
}
public abstract class VotableBase : IVotable
{
public abstract int TotalUpvotes { get; protected set; }
public abstract int TotalDownvotes { get; protected set; }
public virtual int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1 ; } }
}
public class Comment : VotableBase
{
public override int TotalUpvotes { get; protected set; }
public override int TotalDownvotes { get; protected set; }
}
将构图方法融入其中。我一点也不反对继承。但这让我觉得这是一个不使用它的好例子。为什么要限制此 class 只能导出投票功能?我可以想象这个 class 有很多与 "Comment" 更密切相关的东西,例如作者信息(排名、个人简介、头像)、格式、年龄、编辑历史等。其中一些似乎可能更适合作为基础 class.
public interface IVotable
{
int TotalUpvotes { get; }
int TotalDownvotes { get; }
int TotalVoteScore { get; }
}
// shared implementation
public class VoteStatus : IVotable
{
public int TotalUpvotes { get; private set; }
public int TotalDownvotes { get; private set; }
public int TotalVoteScore { get { return TotalUpvotes - TotalDownvotes + 1; } }
}
// has A...
public class Comment : IVotable
{
// expose it?
public IVotable VoteStatus { get; private set; }
// allow current vote status to be injected?
public Comment(IVotable voteStatusReference)
{
this.VoteStatus = voteStatusReference;
}
// or don't use injection?
public Comment()
: this(new VoteStatus())
{
}
public int TotalUpvotes => this.VoteStatus.TotalUpvotes;
public int TotalDownvotes => this.VoteStatus.TotalDownvotes;
public int TotalVoteScore => this.VoteStatus.TotalVoteScore;
}
注意:我也觉得这里的扩展方法建议比继承要好。