抽象函数和数据类型 - 有什么优雅的方法可以做到这一点吗?
本文关键字:这一点 方法 数据类型 什么 抽象函数 | 更新日期: 2023-09-27 18:35:05
我有一个大的对象家族,它们都来自一个父代。 这些对象都知道如何判断它们是否已被修改,但我还需要能够查看对象的新实例是否已被修改,与内存中已有的实例相比(测试以查看其他人是否在编辑对象时更新了数据库。
结果是每个子类都必须包含相同的方法:
public new bool Changed()
{
return Changed(this);
}
这真的让我很纠结,但我认为没有办法解决它,因为真正的工作需要由一个函数来完成,该函数采用与其所在类相同类型的参数——因此它不能是虚拟的。 (当然,我可以定义它以每次都采用父对象并强制转换它,但这会使比较函数接受树中的任何对象,而不仅仅是正确的对象,并且它在每个实例中都需要保护代码,这又是丑陋的东西。
这当然有效,但我不喜欢丑陋的代码。
更新:对于Changed
函数,每个对象在加载时都会保留其状态的副本。
只要你的基类是abstract
,就可以做这样的事情:
abstract class Base
{
public abstract bool Changed<T>(T obj) where T : Base;
public bool Changed()
{
return Changed(this);
}
}
class Subclass : Base
{
public override bool Changed<Subclass>(Subclass obj)
{
// Do stuff here
}
}
基本结构:
public abstract class Base<T> where T : Base<T>
{
public T Original { get; private set; }
public abstract bool Changed(T o);
public bool Changed()
{
return this.Changed(Original);
}
}
public class DerivedA : Base<DerivedA>
{
public override bool Changed(DerivedA o)
{
throw new NotImplementedException();
}
}
public class DerivedB : Base<DerivedB>
{
public override bool Changed(DerivedB o)
{
throw new NotImplementedException();
}
}
虽然它有其缺点(就绪性),但在这种情况下它可能是正确的选择,因为您的问题不是经典动物/狗/猫意义上的类型保护,而是代码共享。
若要防止出现这种情况,请执行以下操作:
public class DerivedC : DerivedB
{
}
new DerivedB().Changed(new DerivedC()); // compiles
你可以封印DerivedB
.
或者你可以继续疯狂(我不建议这样做。绝对不会超过这个水平):
public abstract class DerivedE<T> : Base<DerivedE<T>> where T : DerivedE<T>
{
}
public class DerivedF : DerivedE<DerivedF>
{
}
public class DerivedG : DerivedE<DerivedG>
{
}
new DerivedF().Changed(new DerivedG()); // does not compile
new DerivedF().Changed(new DerivedF()); // does compile
请参阅此 http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx。我从那篇文章中得到了灵感。他讨论了利弊。
编辑:清理,根据评论进行调整
与minitech相同的答案,所以他应该得到荣誉,但在这个例子中,子类A的更改可以通过强制转换为完全命名的类来查看其属性。
namespace ConsoleApplication1
{
abstract class Base
{
protected abstract bool Changed<T>(T obj) where T : Base;
public bool Changed()
{
return Changed(this);
}
public String PropBase { get; set; }
}
class SubclassA : Base
{
public String PropA { get; set; }
protected override bool Changed<SubclassA>(SubclassA obj)
{
ConsoleApplication1.SubclassA myInstance = obj as ConsoleApplication1.SubclassA;
// Now can see PropA
myInstance.PropA = "A";
return true;
}
}
class SubclassB : Base
{
protected override bool Changed<SubclassB>(SubclassB obj)
{
// can't see prop B here
// obj.PropB = "B";
return true;
}
public String PropB { get; set; }
}
class Program
{
static void Main(string[] args)
{
SubclassB x = new SubclassB();
x.Changed();
Base y = new SubclassA();
y.Changed();
}
}
}