![](/img/trans.png)
[英]“this” keyword type when called on an object of derived class from base class
[英]How can a method in a base class return a more derived object based on the type of the object it is called on?
假设您有两个类,如下例所示。
您将如何修改SplitObject使其始终返回类型t的对象,例如在Main()中,它应返回DerivedClass类型的对象?
我猜该解决方案将涉及反思? 我还没有任何有关反射的知识,所以我不知道这将如何工作。
public class BaseClass
{
float _foo;
public BaseClass(float foo){_foo = foo}
public BaseClass SplitObject()
{
Type t = GetType();
// Do something with t
_foo = _foo/2f;
return new BaseClass(_foo); // I want to construct an
// object of type t instead
// of type BaseClass
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(float foo) : base(foo){}
}
class Program
{
static void Main()
{
BaseClass foo = new DerivedClass(1f);
BaseClass bar = foo.SplitObject(); // should return a DerivedObject
}
}
无需反射-只需将SplitObject()
设为虚拟,并在派生类中以不同的方式实现即可。
另一个选择是将Split行为提取到接口中,例如ISplittable<T>
public class BaseClass
{
public virtual BaseClass SplitObject()
{
BaseClass splitObject = new BaseClass();
//initialize the split object
return splitObject;
}
}
public class DerivedClass : BaseClass
{
public override BaseClass SplitObject()
{
DerivedClass derivedSplitObject = new DerivedClass();
//initialize the derived split object
return derivedSplitObject;
}
}
}
如果您真的想使用反射,则可以执行以下操作:
return (BaseClass)Activator.CreateInstance(GetType(), _foo);
当然,现在有一个隐式契约,所有派生类都必须实现这样的构造函数。 不幸的是,此类合同无法在当前的类型系统中指定; 因此在编译时不会发现违规。 埃拉什的想法会更好。 我会做类似的事情:
//... Base class:
public BaseClass SplitObject()
{
_foo = _foo / 2f;
return NewInstance(_foo);
}
protected virtual BaseClass NewInstance(float foo)
{
return new BaseClass(foo);
}
//... Derived class:
protected override BaseClass NewInstance(float foo)
{
return new DerivedClass(foo);
}
如果只希望代码出现在一个位置(更好的维护方式,尤其是在派生类型很多的情况下),则需要使用反射:
public class BaseClass
{
float _foo;
public BaseClass(float foo){_foo = foo;}
public BaseClass SplitObject()
{
Type t = GetType();
_foo = _foo / 2f;
//Find the constructor that accepts float type and invoke it:
System.Reflection.ConstructorInfo ci = t.GetConstructor(new Type[]{typeof(float)});
object o=ci.Invoke(new object[]{_foo});
return (BaseClass)o;
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(float foo) : base(foo) { }
}
class Program
{
static void Main()
{
BaseClass foo = new DerivedClass(1f);
//Cast the BaseClass to DerivedClass:
DerivedClass bar = (DerivedClass)foo.SplitObject();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.