如何将所有对父类的调用转移到子类?

时间:2016-05-20 18:58:27

标签: c# oop inheritance superclass partial-classes

假设我有一个引用包含Class1的dll的C#项目。从Project1,我想通过使用一个继承自Class1的Class2类来扩展Class1的功能,然后我想在Class1被期望时使用Class2(而不修改对Class1的调用指向Class2,这是键的)。

但是,我必须添加Class1是一个初始化模块(在我正在使用的框架中),它没有被明确调用(它是内部机制的一部分)。 这意味着在我的代码中使Class2扩展Class1的行为之后,我无法简单地将Class2的Class1替换为Class1。

(如何)可以实现这一目标?

我想到的另一个想法是使用部分类;但是,我怀疑是否有可能重新定义一个完整的课程'以后'作为一个部分类,在那个dll之外。

=====后来的编辑:我发现了一篇似乎暗示可行的文章,我试图弄清楚如何做。在本文中,它看到RestrictFileTypes(Class2)继承自一个dll中的IInitializableModule(Class1),但它并没有说明Class2从那时起如何替换Class1的所有调用,前进(http://world.episerver.com/blogs/al-higgs/dates/2012/11/Restricting-the-file-types/ )。你是怎么做到的?

2 个答案:

答案 0 :(得分:1)

我不明白第二个要求(“Moreoever ......”)。至于第一种,我看到了两种方式。

您可以编写class2,然后通过手动编辑交换class1和class2的名称。出现的应该很少,只有cs文件名和构造函数。可以保存为首先使用中间名,就像在交换操作中一样。这可能是最简单和最干净的方式,但您可能无法控制当前的class1并且无法重命名它。所以这是另一种方式。

你编写了class2,从一开始就将它命名为class1,但是在另一个命名空间中。您将在另一个名称空间中将class1从另一个class1(旧的)降序。完成后,在每个引用旧class1的文件中为新命名空间添加using指令,并确保它是最后一个使用行,因此它将优先于其上面的那些。如果当前的class1不是引用它的同一名称空间的成员,那么这应该有效。如果是后者,则必须将新命名空间的声明插入到现有命名空间的所有声明中:

namespace ns.of.old.class1
{
    namespace ns.of.new.class1
    {
        [...]
        Some reference to / use of class1
    }
}

使用指令技巧很脆弱,有人可能会注意到这些指令不是按字母顺序排列并右键单击它们,选择“删除并排序”。您的代码可能会被破坏或更糟:仍然可以编译但是再次使用旧的class1。

答案 1 :(得分:1)

我称之为多态,并通过继承实现,如下所示:

var element = data[0];

$("#postjson").append(
  '<div id="' + element.id + '">' + '<p>' + 'FirstName:' + element.FirstName + '<br/>' + 'MiddleName:' + element.MiddleName + '<br/>' + 'LastName:' + element.LastName + '<br/>' + 'Gender:' + element.Gender + '<br/>' + 'Location:' + element.Location + '<br/>' + 'Email:' + element.Email + '<br/>' + 'Mobile:' + element.Mobile + '<br/>' + '</p>' + '</div>'
);

产生输出:

using System;

namespace polymorphismExample {
    public class class1 {
        public virtual string A => "I am Class1.A";
        public         string B => "I am Class1.B";
    }
    public class class2 : class1 {
        public override string A => "I am Class2.A";
    //    public override string B => "I am Class1.B";
        public    new   string B => "I am Class2.B";
    }

    class Program {
        static void Main(string[] args) {
            class1 a1_1 = new class1();

            class1 b1_2 = new class2();
            class2 b2_2 = new class2();

            Console.WriteLine("{0}: {1}", "a1_1.A", a1_1.A);
            Console.WriteLine("{0}: {1}", "a1_1.A", a1_1.B);
            Console.WriteLine();

            Console.WriteLine("{0}: {1}", "b1_2.A", b1_2.A);
            Console.WriteLine("{0}: {1}", "b1_2.A", b1_2.B);
            Console.WriteLine();

            Console.WriteLine("{0}: {1}", "b2_2.A", b2_2.A);
            Console.WriteLine("{0}: {1}", "b2_2.A", b2_2.B);
            Console.WriteLine();   
            Console.ReadLine();
        }
    }
}

请注意a1_1.A: I am Class1.A a1_1.A: I am Class1.B b1_2.A: I am Class2.A b1_2.A: I am Class1.B b2_2.A: I am Class2.A b2_2.A: I am Class2.B 中的注释行是因为它无法编译;因为方法B在class2中不是虚拟的。此模式要求class1不是密封的类,并且只有class1中的方法标记为虚拟(或者当然 abstract )将展示所需的行为:即使在声明为class1类型的变量上调用时,也会调用class2行为。

当然,在任何时候,必须使用class1构造函数初始化变量。