2013-05-30 141 views
1

这里有一些伪代码来说明我在看什么。继承和类内的类

public class Loader 
{ 
    public Execute() 
    { 
     var currentPage = new ItemPageDocumentBuilder(); 
     while(reader.Read()) 
     { 
      currentPage.Add(reader.XmlDoc); 
     } 
    } 

    private class ItemsToLoad 
    { 
     private XmlDocument _page 
     public void Add(XmlElement itemelement) 
     { 
      _page.DocumentElement.AppendChild(itemElement); 
     } 
    } 
} 

我需要获得从装载机一类,然后重写它里面的ItemsToLoad类的Add方法,然后调用base.Execute()。换句话说,我希望派生类的Execute()方法与Loader完全相同,但要使用重载的ItemsToLoad的Add方法来工作。

我怀疑这样做最好的方法是从Loader中删除ItemsToLoad,并使其为抽象的,正确的?

如果我做不到这一点,出于兴趣,最好的解决方案是什么?

+0

您还可以在Loader中注入ItemLoader组件,而不是使用私有内部类。 –

回答

1

开始,你有两个responsabilities:执行的东西(这始终是一样的),并添加一些(而不同)。

我会做得更简单,没有继承和内部类。

对于添加任务,你定义一个接口:

public interface IItemAdder 
{ 
    void Add(); 
} 

与一个或多个实现:

public class ItemAdder1 : IItemAdder 
{ 
    public void Add() 
    {    
     // specific implementation here 
    } 
} 

然后,你有装载机,其你注入项目的特定实例加法:

public class Loader : ILoader 
{ 
    private IItemAdder _itemAdder; 
    public Loader(IItemAdder itemAdder) 
    { 
     _itemAdder = itemAdder; 
    } 
    public void Execute() 
    { 
     // use injected item adder to do work 
     _itemAdder.Add(); 
    }  
} 

public interface ILoader 
{ 
    void Execute(); 
} 

所以用法是:

var loader = new Loader(new ItemAdder1()); 
loader.Execute();  

这样一切都被注入,可以轻易替换和嘲笑;你清楚地分开关注。

+0

谢谢。尽管我将Interfaced集合添加为虚拟属性,而不是将其注入,但我最终采用了此路由。 –

+0

构造函数是更好的解决方案的原因是您明确定义了所需的依赖关系,因此您了解它们事先,你必须在创建你的课程实例时注入它们。对于属性注入来说,这不是一个明确的依赖。 –

+0

是的,我明白这是很好的建议。但在这种情况下,它会打破太多的依赖架构来更改构造函数。它已被标记为以后重构现在的问题解决:) –

0

这里有一个建议(语法可能不正确,虽然):

public class Loader 
{ 
    ItemsToLoad item; 
    public Loader(ItemsToLoad item) { 
     this.item = item; 
    } 

    public Execute() 
    { 
     // do things using item like item.add(); 
    } 
} 

interface ItemsToLoad 
{ 
    void add(); 
} 

class ItemsToLoad1: ItemsToLoad 
{ 
    void add(){ 
     // implementation 
    } 
} 

class ItemsToLoad2: ItemsToLoad 
{ 
    void add(){ 
     // implementation 
    } 
} 

这里是如何使用它们;

ItemsToLoad item; 
if (some condition) { 
    item = new ItemsToLoad1() 
} else { 
    item = new ItemsToLoad2() 
} 

Loader loader = new Loader(item); 
loader.execute(); 
0

您可以继承这两个类并将子子类对象注入其父类。

class Loader 
    { 

     public void Execute(ItemsToLoad argObj) 
     { 
      if(argObj == null) 
       argObj = new ItemsToLoad(); 

      argObj.Add(19); 
     } 

     public class ItemsToLoad 
     { 
      public virtual void Add(int a) 
      { 
       Console.WriteLine("Reached ItemsToLoad."); 
      } 
     } 
    } 

class ChildLoader:Loader 
    { 
     public void Execute(ItemsToLoad argObjLoader) 
     { 
      if (argObjLoader == null) 
       argObjLoader = new ChildItemsToLoad(); 

      base.Execute(argObjLoader); 
    } 

    class ChildItemsToLoad : Loader.ItemsToLoad 
    { 

     public override void Add(int b) 
     { 
      Console.WriteLine("Reached ChildItemsToLoad."); 
     } 

    } 
} 

,如果我理解你的要求可以用

ChildLoader obj999 = new ChildLoader(); 
obj999.Execute(null); 
0

我需要从Loader派生一个类,然后重写其中的ItemsToLoad类的Add方法,然后调用base.Execute()。换句话说,我希望派生类的Execute()方法与Loader完全相同,但要使用重载的ItemsToLoad的Add方法来工作。

您需要覆盖Loader而不是ItemsToLoad。您尚未显示使用ItemsToLoad的代码,因此很难具体说明 - 但至少您需要覆盖new ItemsToLoad以指向您的子类。此外,ItemsToLoad是私人的 - 这意味着你不能使用它,除了从Loader内。现在,您需要完全重写ItemsToLoad并覆盖使用ItemsToLoadLoader中的每个方法。

如果您控制Loader类,最简单的更改可能是抽象出创建ItemsToLoad并打开ItemsToLoad,因此它可以被分类。例如:

public class Loader { 
    private ItemsToLoad Items { get; set; } 

    protected virtual ItemsToLoad CreateItemsToLoad() { 
     return new ItemsToLoad(); 
    } 

    protected class ItemsToLoad { 
     public virtual void Add() { 
     } 
    } 
} 

public class MyOtherLoader : Loader { 
    protected override ItemsToLoad CreateItemsToLoad() { 
     return new MyOtherItemsToLoad(); 
    } 

    private class MyOtherItemsToLoad : ItemsToLoad { 
     public override void Add() { 
     } 
    } 
}