2014-03-06 18 views
5

我想弄清楚派生类由具有比抽象基类中指定的更具体类型的成员组成的方法。这里有一些代码可以做我想做的事,但不遵循我提到的规定。因此,我想,客户端代码(在Main中)必须在“BarProperty”上使用一个强制转换,这正是我想要避免的。如何才能达到覆盖更具体类型的基础成员的效果?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Stackoverflow 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      ConcreteFoo myFoo = new ConcreteFoo(); 
      myFoo.BarProperty = new ConcreteBar(); 

      ((ConcreteBar)myFoo.BarProperty).ConcreteBarPrint(); 

      Console.ReadKey(); 
     } 
    } 

    abstract class AbstractFoo 
    { 
     protected void FooMethod() 
     { 
      Console.WriteLine("The Foo method!"); 
     } 

     public abstract AbstractBar BarProperty { get; set; } 
    } 

    class ConcreteFoo : AbstractFoo 
    { 
     private ConcreteBar _concreteBar; 

     public override AbstractBar BarProperty 
     { 
      get 
      { 
       return _concreteBar; 
      } 
      set 
      { 
       _concreteBar = (ConcreteBar)value; 
      } 
     } 
    } 

    abstract class AbstractBar 
    { 
     protected void BarMethod() 
     { 
      Console.WriteLine("The Bar method!"); 
     } 

    } 

    class ConcreteBar : AbstractBar 
    { 
     public List<int> concreteBarIntList; 

     public ConcreteBar() 
     { 
      concreteBarIntList = new List<int>(); 
      concreteBarIntList.Add(1); 
      concreteBarIntList.Add(2); 
      concreteBarIntList.Add(3); 
     } 

     public void ConcreteBarPrint() 
     { 
      foreach (int item in concreteBarIntList) 
      { 
       Console.WriteLine(item); 
      } 
     } 

    } 
} 

想我反而会做类似下面的代码,这当然不能编译,因为ConcreteFoo尝试使用比AbstractFoo宣布为更具体的类型覆盖BarProperty。

你也许会想“重新考虑你的设计”,但它的棘手,因为我试图将一些第三方的代码(不改变代码)不包含一些急需的抽象/接口类给两个非常相似的代码库的可互换外观。因此,我基本上必须编写我的整个程序两次,只对使用什么类型做了小的改动。我需要一些方法来处理两个非常相似的类型,不幸的是它们没有一个接口来展示它们与编译器的相似性。

+0

你担心了'GET'或'set'? – Guvante

回答

8

对于基本方案,尝试给BarProperty一个generic type with a constraint

public abstract class AbstractFoo<TBar> where TBar : AbstractBar 
{ 
    public abstract TBar BarProperty { get; } 
} 

public class ConcreteFoo : AbstractFoo<ConcreteBar> 
{ 
    public override ConcreteBar BarProperty { get { ...; } } 
} 

根据补充意见,这听起来像在这种特殊情况下,真正的挑战是不共享一个基本类型或接口的多个类,但具有相似的形状和行为。在这种情况下,一个解决方案是创建一个代理类

public class MyProxy 
{ 
    private readonly Foo _foo; 
    private readonly Bar _bar; 

    public MyProxy(Foo foo) 
    { 
     this._foo = foo; 
    } 

    public MyProxy(Bar bar) 
    { 
     this._bar = bar; 
    } 

    public string SharedProperty1 
    { 
     get 
     { 
      if(this._foo != null) 
      { 
       return this._foo.SharedProperty1; 
      } 
      if(this._bar != null) 
      { 
       return this._bar.SharedProperty1; 
      } 
      throw new InvalidOperationException("Both underlying objects are null"); 
     } 
    } 
} 
+0

嗯...我一直在试图找出一些方法来涉足仿制药,但一直没能想到的正确方法。我会看看我是否可以将这种方法应用到我正在开发的项目中。它可能需要我整天;)但我会回来更多的评论和/或选择这个答案后,我可以尝试一下。 – bubbleking

+0

如果您想在列表中引用一堆abstractFoo,并且可能有多种类型从不同的实现返回,那该怎么办?我可以使用更通用的东西吗?然后AbstractFoo ?像AbstractFoo? – Eluvatar

+0

@Eluvatar你可以建立一个像'MultiFoo实现:AbstractFoo ' –

相关问题