如何指定要使用其类型的子类
本文关键字:类型 子类 何指定 | 更新日期: 2023-09-27 18:10:42
假设我有这样一个类:
public abstract class Foo
{
public void Access(Foo foo)
{
/*
if (foo is same type as implemented)
AccessIfSameImplementation(foo);
else
AccessIfDifferentImplementation(foo);
*/
}
protected abstract void AccessIfSameImplementation(Foo foo);
private void AccessIfDifferentImplementation(Foo foo)
{
//do stuff with the different implementations
}
}
因此,方法Access
本身就有一种类型,根据定义,只要它继承自Foo
,我们就不会真正关心它是什么。。。但我希望此方法检查传入的对象是否与其实现的类型相同。
像这样:
public class Bar : Foo
{
protected override void AccessIfSameImplementation(Foo foo)
{
// TODO: How do I force foo to always be a Bar
// do specific Bar stuff
}
}
目前,我有一个Name
字段,它指示传入的foo.Name
是否与当前的Name
相同。此外,我曾想过使用泛型,但再次认为这不是解决这个问题的正确方法。
编辑:
关于我正在使用的实际结构的一些背景知识。
上面定义的Foo
类代表创建一组对象List<X> objs
的工厂,这些对象是由实现的Foo
对象的属性生成的。现在我有一些其他类比较这些工厂,但我不希望这些工厂因为全部生产而变得臃肿。因此,我不想让工厂膨胀,而是简单地检查它们是否有相同的实现,如果是,则比较抽象比较器定义的属性,否则就会井喷。稍后有时间我会添加更多内容。
如果有人有更好的头衔,请推荐一个。
空着,所以我想我就是想不透。所有需要做的就是直接在公共方法Access
中进行类型比较
public void Access(Foo foo)
{
if (GetType() == foo.GetType) //Duh...
{
AccessIfSameImplementation(foo);
}
else
{
AccessIfDifferentImplementation(foo);
}
}
我不完全确定您的意图是什么,但您不能更改子类中抽象方法的签名。一个想法是,如果你得到了一个不合适的foo:,就进行参数检查并抛出异常
public abstract class Foo
{
public void Access(Foo foo)
{
if (foo.GetType() == GetType())
{
AccessIfSameImplementation(foo);
}
else
{
AccessIfDifferentImplementation(foo);
}
}
protected abstract void AccessIfSameImplementation(Foo foo);
private void AccessIfDifferentImplementation(Foo foo)
{
//do stuff with the different implementations
}
}
public class Bar : Foo
{
public string Baz { get; set; }
protected override void AccessIfSameImplementation(Foo foo)
{
var bar = foo as Bar;
if (bar == null)
{
throw new ArgumentException("Argument foo is not of type Bar");
}
//Do Bar stuff below
bar.Baz = "Yay!";
}
}
保持简单。保持抽象类的抽象性,但为Access
方法提供一个与Foo
无关的默认实现。让它作为一个子类来提供使用该子类成员的自定义实现。您还可以使子类可以选择返回基类中实现的默认逻辑:
public abstract class Foo
{
public virtual void Access(Foo foo)
{
// perform the default implementation here, but mark as virtual to enable a child class to override it.
}
}
public class Bar : Foo
{
public override void Access(Foo foo)
{
var bar = foo as Bar;
if (bar != null)
{
// If you get here, that means foo is a Bar.
// Just use bar now and ignore foo.
}
else
{
// Fall back on the base classes implementation
base.Access(foo);
}
}
}