给出以下示例:
class A { }
class B : A { }
class C : A { }
我希望所有继承的类都实现一个函数,该函数执行特定于这些类的不同实例的数据的比较。我面临的问题是其中一个参数与实现此方法的类的类型相同。类似的东西:
class A
{
public virtual void CompareSomeData(A instanceOfA) { }
}
class B : A
{
public override void CompareSomeData(B instanceOfB)
{
base.CompareSomeData(instanceOfB);
}
}
class C : A
{
public override void CompareSomeData(C instanceOfC)
{
base.CompareSomeData(instanceOfC);
}
}
显然你不能以这种方式覆盖C#中的方法。那么最好的模式是什么?
public virtual void CompareSomeData(object instance, Type typeOfInstance)
{
// Cast the object to an instance of the type here?
}
OR
public virtual void CompareSomeData(A instanceOfA, Type typeOfInstance)
{
// Cast the object to an instance of the type here?
}
或其他一些方法?
这里的想法是我想从具有类型约束的泛型方法调用这些方法:
private void CompareData<T>(List<T> dataOld, List<T> dataNew) where T : A
{
foreach (T item in dataNew)
{
item.CompareSomeData(GetItemToCompare(dataOld));
}
}
我仍然看到我的建议和Marc的答案的问题是这些确实不是类型安全的。如果没有检查方法(if (instanceOfA is B) { ... }
),我无法保证传递给B的对象真的是B。我不知道是否有任何解决方法,但我可能只需要使用它并抛出ArgumentException
或其他东西。
答案 0 :(得分:2)
覆盖时无法更改签名,但在并行覆盖时可以重载方法,例如:
class A {
public virtual void CompareSomeData(A instanceOfA) { }
}
class B : A {
public void CompareSomeData(B instanceOfB) {
// ...
}
public override void CompareSomeData(A instanceOfA) {
// ...
}
}
请注意,这两种方法中的一种调用另一种方法(仅在一个地方使用逻辑)是常见的 - 但应调用哪种方法是特定于实现的。
另请注意,如果您只是更改返回类型,则需要采用不同的方式:
class A {
public bool CompareSomeData(A instanceOfA) {
return CompareSomeDataImpl(instanceOfA);
}
protected virtual bool CompareSomeDataImpl(A instanceOfA)
{ return true; }
}
class B : A {
public new string CompareSomeData(A instanceOfA) {
// ...
}
protected override bool CompareSomeDataImpl(A instanceOfA) {
// ...
}
}
答案 1 :(得分:1)
这很丑陋,但有一种方法可以确保类型安全而不需要强制转换或要求类知道继承它们的类是:
interface IDataComparer<T>
{
void CompareSomeData(T instance);
}
class A : IDataComparer<A>
{
public virtual void CompareSomeData(A instanceOfA) { }
}
class B : A, IDataComparer<B>
{
public override void CompareSomeData(A instanceofA)
{
throw new ArgumentException("...");
}
public virtual void CompareSomeData(B instanceOfB)
{
base.CompareSomeData(instanceOfB);
}
}
class C : A, IDataComparer<C>
{
public override void CompareSomeData(A instanceofA)
{
throw new ArgumentException("...");
}
public virtual void CompareSomeData(C instanceOfC)
{
base.CompareSomeData(instanceOfC);
}
}
然后在CompareData<T>
方法中,您将使用约束T : IDataComparer<T>
答案 2 :(得分:1)
快速免责声明(Rant):
我不太喜欢方法重载(相同的标识符,不同的参数类型或不同的参数的数量。)。而且,如果它与方法重写(虚拟方法)混合在一起,事情变得更加复杂。
提出的解决方案:
反转过程。而不是重载或覆盖处理参数的类,重载或覆盖作为参数的类。
public abstract class ParameterDataClass
{
public abstract bool CompareTo(StreamClass Stream);
} // class ParameterDataClass
public /* concrete */ class DataComparerClass
{
internal /* nonvirtual */ void InternalComparison(string Data) { ... }
public /* nonvirtual */ bool CompareThis(ParameterDataClass Data)
{
bool Result = false;
if (Data != null)
{
Result = Data.CompareTo(this);
}
} // bool CompareThis(...)
} // class StreamClass
public /* concrete */ class CustomerClass: StreamDataClass
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
public override bool CompareTo(StreamClass Stream)
{
bool Result = false;
if (Stream!= null)
{
string Temp = "{" +
FirstName.ToString() + "," +
LastName.ToString() + "," +
BirthDate.ToString() + "}"
Result = Data.CompareTo(Temp);
}
} // bool CompareTo(...)
return Result;
} // class CustomerClass
public /* concrete */ class AreaClass: StreamDataClass
{
public int Top { get; set; }
public int Left { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public override bool CompareTo(StreamClass Stream)
{
bool Result = false;
if (Stream!= null)
{
string Temp = "{" +
Top.ToString() + "," +
Left.ToString() + "," +
Width.ToString() + "," +
Height.ToString() + "}"
Result = Data.CompareTo(Temp);
}
} // bool CompareTo(...)
return Result;
} // class AreaClass
public /* concrete */ class IntegerClass: StreamDataClass
{
public int RealVaLue { get; set; }
public override bool CompareTo(StreamClass Stream)
{
bool Result = false;
if (Stream!= null)
{
Result = Data.CompareTo(RealValue.ToString());
}
} // bool CompareTo(...)
return Result;
} // class IntegerClass
我不记得这种技术的名称,“访客模式”,“调度”等等。
希望它有所帮助。
P.S。不要忘记为猫咪提供一个开放的金枪鱼罐头