代码之家  ›  专栏  ›  技术社区  ›  zildjohn01

C-在我没有写的类中使用多态性

  •  2
  • zildjohn01  · 技术社区  · 17 年前

    在我不能修改的类中实现多态行为的最佳方法是什么?我现在有一些代码,比如:

    if(obj is ClassA) {
        // ...
    } else if(obj is ClassB) {
        // ...
    } else if ...
    

    显而易见的答案是向基类中添加一个虚拟方法,但不幸的是,代码在另一个程序集中,我无法修改它。有没有比上面的丑陋和缓慢的代码更好的方法来处理这个问题?

    5 回复  |  直到 12 年前
        1
  •  9
  •   harpo Binary Worrier    17 年前

    六羟甲基三聚氰胺六甲醚。。。似乎更适合 Adapter .

    public interface ITheInterfaceYouNeed
    {
        void DoWhatYouWant();
    }
    
    public class MyA : ITheInterfaceYouNeed
    {
        protected ClassA _actualA;
    
        public MyA( ClassA actualA )
        {
            _actualA = actualA;
        }
    
        public void DoWhatYouWant()
        {
            _actualA.DoWhatADoes();
        }
    }
    
    public class MyB : ITheInterfaceYouNeed
    {
        protected ClassB _actualB;
    
        public MyB( ClassB actualB )
        {
            _actualB = actualB;
        }
    
        public void DoWhatYouWant()
        {
            _actualB.DoWhatBDoes();
        }
    }
    

    似乎有很多代码,但它会使客户机代码更接近您想要的代码。此外,它还可以让您有机会考虑实际使用的界面。

        2
  •  5
  •   Community Mohan Dere    9 年前

    退房 Visitor 模式。这使您可以在不更改类的情况下向类中添加虚拟方法。如果正在使用的基类没有访问方法,则需要将扩展方法与动态强制转换一起使用。下面是一些示例代码:

    public class Main
    {
        public static void Example()
        {
            Base a = new GirlChild();
            var v = new Visitor();
            a.Visit(v);
        }
    }
    
    static class Ext
    {
        public static void Visit(this object b, Visitor v)
        {
            ((dynamic)v).Visit((dynamic)b);
        }
    }
    
    public class Visitor
    {
        public void Visit(Base b)
        {
            throw new NotImplementedException();
        }
    
        public void Visit(BoyChild b)
        {
            Console.WriteLine("It's a boy!");
        }
    
        public void Visit(GirlChild g)
        {
            Console.WriteLine("It's a girl!");            
        }
    }
    //Below this line are the classes you don't have to change.
    public class Base
    {
    }
    
    public class BoyChild : Base
    {
    }
    
    public class GirlChild : Base
    {
    }
    
        3
  •  0
  •   Noldorin    17 年前

    我想说,这里的标准方法是将要“继承”的类包装为受保护的实例变量,然后在容器类中模拟包装类的所有非私有成员(方法/属性/事件等)。然后,您可以将这个类及其适当的成员标记为虚拟的,这样您就可以使用它的标准多态特性。

    这是我的意思的一个例子。 ClosedClass 程序集中包含的类,其代码您无权访问。

    public virtual class WrapperClass : IClosedClassInterface1, IClosedClassInterface2
    {
        protected ClosedClass object;
    
        public ClosedClass()
        {
            object = new ClosedClass();
        }
    
        public void Method1()
        {
            object.Method1();
        }
    
        public void Method2()
        {
            object.Method2();
        }
    }
    

    如果您所引用的程序集设计得很好,那么您可能希望访问的所有类型/成员都将被适当地标记(抽象、虚拟、密封),但实际上并非如此(有时您甚至可以在基类库中遇到此问题)。在我看来,包装类是这里的方法。它确实有它的好处(即使当您想要从中派生的类 可继承),即删除/更改不希望类用户访问的方法的修饰符。这个 ReadOnlyCollection<T> 在BCL中是一个很好的例子。

        4
  •  0
  •   Rezlaj    17 年前

    看看 Decorator 模式。诺尔多林没有说出模式的名字就解释了这一点。

    decorator是在不继承的情况下扩展行为的方法。在noldorin的代码中,我唯一要改变的是,构造函数应该接收到您正在修饰的对象的一个实例。

        5
  •  -1
  •   Adam Lassek    17 年前

    Extension methods 提供一种向现有类添加其他方法签名的简单方法。这需要3.5框架。

    创建一个静态实用程序类并添加如下内容:

    public static void DoSomething(this ClassA obj, int param1, string param2)
    {
        //do something
    }
    

    在页面上添加对实用程序类的引用,此方法将显示为类A的成员。您可以通过这种方式重载现有方法或创建新方法。