这是一个,我有一个像这样的抽象类...
public abstract class SpaceshipManager
{
...
public abstract void BuildWith(ParseObject po);
// "Or ..."
public abstract void BuildWith(string label);
...
}
从某种意义上讲,派生类必须实现BuildWith ParseObject,“OR”,它们可以使用字符串实现BuildWith。
现在,我刚刚这样做......
public abstract void BuildWith(object data);
哪个好 - 但是有更好的方法吗?
另一种看待它的方法,你可以有两种方法
BuildKeidranType()
BuildBastionType()
概念是派生类必须至少实现其中一个。
c#中有没有这样的东西?
答案 0 :(得分:3)
您可以使用泛型:
public abstract class SpaceshipManager<T>
{
public abstract void BuildWith(T source);
}
public class StringBuilderSpaceshipManager : SpaceshipManager<ParseObject> { ... }
答案 1 :(得分:2)
在c#中没有类似的东西。 Generics
本可以给你一个出路。
但是看到你是从MonoBehavior
派生的,我假设你正在使用它Unity
,其中有类名称必须与文件名等相同的约束等。没有为通用行为提供太多选择。因此,避免使用泛型类并专注于泛型方法。
以下是一个非常粗略的示例,使用泛型只是为了好玩,并且可能不比您将参数作为对象的当前示例好多少。不过这里有:
public abstract class SpaceshipManager: MonoBehaviour
{
public void BuildWith<T>(T po)
{
if (ValidateBuildParam<T>())
{
Build<T>(po);
}
}
protected abstract bool ValidateBuildParam<T>();
protected abstract void Build<T>(T type);
}
public class DerivedA : SpaceshipManager
{
protected override void Build<T>(T po)
{
//Build here
}
protected override bool ValidateBuildParam<T>()
{
return (typeof(T) != typeof(ParseObject)) ? false : true;
}
}
public class DerivedB : SpaceshipManager
{
protected override void Build<T>(T po)
{
//Build here
}
protected override bool ValidateBuildParam<T>()
{
return (typeof(T) != typeof(string)) ? false : true;
}
}
现在有一些缺点,例如以下用法不正确:
SpaceshipManager spMan = new DerivedA();
spMan.BuildWith<int>(5);
这将编译并运行,但不会构建任何东西。因此,如果更改BuildWith的返回类型,如果验证失败或bool true
或false
答案 2 :(得分:1)
不,没有这样的事情。
如果派生类只实现了其中一个重载,那么调用者将如何知道实现了哪一个?
答案 3 :(得分:1)
不,你要问的这些东西在c#中没有。在c#中有接口,但你必须在派生类中实现所有方法,因为如果你实现其中一个调用者会感到困惑。
答案 4 :(得分:0)
正如其他人已经告诉过你的那样,你不能将抽象方法定义为可选的以某种方式实现。
如果可能,我建议定义一些可以作为BuildWith
方法输入的常见类型。例如,label
字符串是否也可以表示为ParseObject
?如果没有,你能想到两者的一些共同抽象吗?
如果这两个问题的答案都是否定的,那么我认为这两种方法可能不应该首先超载。
如果答案是肯定的,那么你只能将其中一种方法抽象化:
public abstract class SpaceshipManager : MonoBehaviour
{
public abstract void BuildWith(ParseObject po);
public void BuildWith(string label)
{
// Static method or constructor here to represent label as a ParseObject.
BuildWith(ParseObject.FromLabel(label))
}
}
在这个例子中,ParseObject是常见的抽象。它也可以是另一个类或接口。
根据具体情况,@Lee发布的泛型选项也可能是一个很好的解决方案,可能与非通用基类型相结合:
abstract class SpaceshipManager<T> : SpaceshipManager
{
public abstract void BuildWith(T source);
}
abstract class SpaceshipManager
{
// Other methods here
}
如果这些解决方案都不适合您,您可以随时将方法设为虚拟,并在需要时覆盖该行为,但这种设计在您的情况下有意义,这有点令人怀疑。
答案 5 :(得分:0)
您可以实现两个接口。 IBuildWithFromString
和IBuildWithFromParseObject
。然后,您可以通过尝试强制转换到此接口来查询实现哪个接口,如果成功,您可以调用相应的方法。