听起来很愚蠢,但我想知道它是否有可能。
是否可以在运行时更改派生类的基类?当然,有很多ifs和buts以及为什么会有人这样做以及它可能是一个糟糕的设计的问题。
将所有这些放在一边(即使它们可能完全有效),让我们说,只是为了踢或显示你的神经质,是否可能用C#或任何语言来解决这个问题?
类似于:
public class baseOriginal {
public string justAProperty;
}
public class baseSwapped {
public int sillyNumber;
}
public class derivedClass : baseOriginal {
public bool iAmDumb;
}
void Main() {
baseOriginal derived = new derivedClass ();
Console.WriteLine(derived.justAProperty);
baseSwapped derivedSwapped = (??);
Console.WriteLine(derivedSwapped.sillyNumber);
}
答案 0 :(得分:1)
在C#中是不可能的。您可能想要的更多是基于原型的解决方案,这种解决方案常见于JavaScript等动态语言中,您可以通过添加对象的功能来“扩展”对象的功能。
但要完成代码提示的操作,可以让swappable类继承自共同的祖先类。这样,您可以将每个实例分配给其后代。
public class baseClassAncestor{
}
public class baseOriginal:baseClassAncestor {
public string justAProperty;
}
public class baseSwapped:baseClassAncestor {
public int sillyNumber;
}
public class derivedClass : baseOriginal {
public bool iAmDumb;
}
答案 1 :(得分:1)
您可以通过使用派生类加载实现基类BEFORE的不同程序集来执行一次基类交换。但是这种方法不会使你的确切代码工作,因为你将无法编译 - 但是可以使对不同基类的方法的访问移动到单独的函数。
添加包含所有基类中所有可能方法/属性的UnionBase类,以便您可以针对具有此类的程序集编译Main代码。比在运行时加载包含特定基类的程序集。
常见警告:你需要有很好的理由和理解才能走这条路。即现有的外部代码是考虑这种方法的一个原因。
“不要在家里做,由训练有素的专业人员在封闭的课程上进行”。
答案 2 :(得分:1)
答案 3 :(得分:1)
实际上有一个很好的理由可能需要交换基类。假设您要修改基类,但不要因为它在其他团队之间共享而不打扰当前的代码库。假设有10个派生类继承自base。您可以创建10个以上的自定义派生类来覆盖基类,但这是很多工作。这是你做的。问题的关键是创建一个接口和一个基本代理类。
class Program
{
static void Main(string[] args)
{
IActionable action = new Derived<Base1>();
action.open();
action = new Derived<Base2>();
action.open();
}
}
// Proxybase is a fake base class. ProxyBase will point to a real base1 or
// base2
public class Derived<T>:ProxyBase,IActionable
{
public Derived():base(typeof(T))
// the open function is not overriden in this case allowing
// the base implementation to be used
}
// this looks like the real base class but it is a fake
// The proxy simply points to the implementation of base1 or base2 instead
public abstract class ProxyBase: IActionable
{
IActionable obj;
public ProxyBase(Type type,params object[] args)
{
obj = (IActionable)Activator.CreateInstance(type,args);
}
public virtual void open()
{
obj.open();
}
}
// notice base1 and base2 are NOT abstract in this case
// consider this the original implementation of the base class
public class Base1: IActionable
{
public virtual void open()
{
Console.WriteLine("base1 open");
}
}
// here base2 acquired the functionality of base1 and hides base1's open
function
// consider this implementation the new one to replace the original one
public class Base2: Base1, IActionable
{
public new virtual void open()
{
Console.WriteLine("base2 open");
}
}
public interface IActionable
{
void open();
}
结果如下
base1 open
base2 open
更新: 虽然这个答案有效,但事实是继承引入了耦合,这使得这个练习充其量只是困难。此外,在实际情况中,您的要求可能会导致您希望从c#中无法实现的多个基类派生。如果要交换基类,最好使用桥接设计模式(这实际上完全避免了继承,从而避免了耦合)。
答案 4 :(得分:0)
最接近的可能是通过将至少一个定义为接口,然后从一个派生到另一个派生来从两种类型派生。
答案 5 :(得分:0)
我能想到的最接近的事情如下:
http://msdn.microsoft.com/en-us/library/dd264736.aspx
static void Main(string[] args)
{
ExampleClass ec = new ExampleClass();
// The following line causes a compiler error if exampleMethod1 has only
// one parameter.
//ec.exampleMethod1(10, 4);
dynamic dynamic_ec = new ExampleClass();
// The following line is not identified as an error by the
// compiler, but it causes a run-time exception.
dynamic_ec.exampleMethod1(10, 4);
// The following calls also do not cause compiler errors, whether
// appropriate methods exist or not.
dynamic_ec.someMethod("some argument", 7, null);
dynamic_ec.nonexistentMethod();
}
class ExampleClass
{
public ExampleClass() { }
public ExampleClass(int v) { }
public void exampleMethod1(int i) { }
public void exampleMethod2(string str) { }
}
我不知道动态语言运行时是否可以执行您希望它执行的操作。
最接近你可能会得到 通过定义at来从两种类型派生 然后,至少有一个作为接口 铸造从一个铸造到另一个。
我必须同意,根据这个例子,这个建议会满足他想要做的事情,这也是一个更好的设计然后他真正想做的事情。