我知道有人问过类似的问题,但我没有发现任何与我所做的足够相似的问题。
假设我有这个:
public interface IData
{
string Data { get; set; }
}
public interface IJob<out T> where T: IData
{
T JobData { get; } // works because no setter
void Run();
}
public class JobAData : IData
{
public string Data { get; set; }
}
public class JobA : IJob<JobAData>
{
public JobAData JobData { get; private set; } // implements IJob's get plus a set
public JobA(JobAData data)
{
JobData = data;
}
public void Run()
{
//can use JobData nicely here
}
}
而且,由于out参数,这也起作用:
List<IJob<IData>> jobs = new List<IJob<IData>>();
jobs.Add(new JobA(new JobAData()));
//in another class, extremely simplified (actually running with Quartz)
foreach (var job in jobs)
{
job.Run();
}
虽然这很好,但感觉就像一次黑客攻击,因为我必须记住,JobA
需要一个不受接口强制执行的setter。
我最初使用的是双IJob
接口( IJob
和IJob<T>
),但这意味着我不得不从IJob<T>
转换到IJob
,我不喜欢这样做。
有什么更干净的方法吗?
发布于 2017-06-27 06:56:21
更新
我最初的建议是创建一个抽象类来设置构造函数中的数据,
public abstract class JobBase<T> : IJob<T> where T : IData {
public JobBase(T data) {
JobData = data;
}
public T JobData { get; private set; }
public abstract void Run();
}
强制派生类设置JobData
属性。
public class JobA : JobBase<JobAData> {
public JobA(JobAData data) : base(data) { }
public void Run() {
//can use JobData nicely here
}
}
原始答案
遵循抽象基类的思想,考虑一个抽象工厂方法,它将强制任何派生类提供数据,无论是在属性本身中。
public abstract class JobBase<T> : IJob<T> where T : IData {
public T JobData { get { return GetData(); } }
public abstract void Run();
public abstract T GetData();
}
或者有一个私有的setter并在构造函数中设置它一次
public abstract class JobBase<T> : IJob<T> where T : IData {
public JobBase() {
JobData = GetData();
}
public T JobData { get; private set; }
public abstract void Run();
public abstract T GetData();
}
任何派生实现都将被迫实现GetData
方法。
发布于 2017-06-27 06:02:05
据我所知,您希望在继承上强制执行setter定义,这也会有可访问性限制!如果定义了setter方法,那么最终还是会使其公开访问。而且,“双IJob
接口( IJob
和IJob<T>
) --但这意味着我不得不从IJob<T>
转换为IJob
--”对您来说不是很好。
对于这种情况,没有太多的解决方案,但是可以使用抽象类进行限制。我的建议是这样的:
public interface IData
{
string Data { get; set; }
}
public interface IJob<out T> where T : IData
{
T JobData { get; }
void Run();
}
public class JobAData : IData
{
public string Data { get; set; }
}
public abstract class Abs_JobA : IJob<JobAData>
{
public abstract JobAData JobData { get; protected set; }
public abstract void Run();
}
public class JobA : Abs_JobA
{
public override JobAData JobData
{
get;
protected set;
}
public JobA(JobAData data)
{
this.JobData = data;
}
public override void Run()
{
//can use JobData nicely here
}
}
所以现在,您没有将IJob
实现到后续类,而是扩展了Abs_JobA
抽象类。
https://stackoverflow.com/questions/44780070
复制相似问题