2013-05-30 5 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); 
     } 
    } 
} 

Мне нужно получить класс от погрузчика, а затем переопределить метод Add класса ItemsToLoad внутри него, а затем вызвать base.Execute(). Другими словами, я хочу, чтобы метод Execute() моего производного класса был точно таким же, как и у Loader, но для использования переопределенного метода AddToLoad Add для его работы.

Я подозреваю, что самый простой способ сделать это - удалить ItemsToLoad изнутри Loader и сделать его абстрактным, правильным?

Если бы я не мог этого сделать, из интереса, какое наилучшее решение?

+0

Вы также можете ввести компонент ItemLoader в Loader вместо использования частного внутреннего класса. –

ответ

1

Если я правильно понимаю ваши требования, у вас есть два удовлетворения претензий: выполнение что-то (что всегда то же самое), и добавляя что-то (что отличается).

Я бы сделал это намного проще, без наследования и внутренних классов.

Для добавления задачи необходимо определить интерфейс:

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, а затем переопределить метод Add из класса ItemsToLoad внутри него, а затем вызвать base.Execute(). Другими словами, я хочу, чтобы метод Execute() моего производного класса был точно таким же, как и у Loader, но для использования переопределенного метода AddToLoad Add для его работы.

Вам необходимо переопределить Loader, а не ItemsToLoad. Вы не указали код, который использует ItemsToLoad, поэтому трудно быть конкретным - но, по крайней мере, вам нужно переопределить new ItemsToLoad, чтобы указать на ваш подкласс. Кроме того, ItemsToLoad является конфиденциальным - это означает, что вы не можете его использовать, кроме как в пределах Loader.Как и сейчас, вам нужно полностью переписать ItemsToLoad и переопределить каждый метод в Loader, который использует ItemsToLoad.

Если вы управляете классом 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() { 
     } 
    } 
} 
Смежные вопросы