2015-05-29 3 views
3

Учитывая приведенный ниже код,Рефакторинг конкретного метода в абстрактном классе, который содержит абстрактный метод

abstract class AbstractClass 
{ 
public abstract void AbstractMethodA(); 
public void ConcreteMethodA() 
{ 
    //Some operation 
    ConcreteMethodB(); 
} 
} 

public void ConcreteMethodB() 
{ 
    //Huge code unrelated to this class 
    AbstractMethodA(); 
} 
} 

class DerivedClass : AbstractClass 
{ 
public void AbstractMethodA() 
{ 
//Some operation 
} 
} 

Сейчас я хочу, чтобы переместить ConcreteMethodB() в отдельный класс и сделать вызов это от метода ConcreteMethodA() в абстрактном классе. Но так как ConcreteMethodB() использует абстрактный метод AbstractMethodA(), реализованный в DerivedClass, я не могу получить доступ к методу AbstractMethodA() из нового класса? Любая идея о том, как разрешить это?

ответ

7

Почему вы не сделать это как этот

static class Helper { 
public static void ConcreteMethodB(AbstractClass caller) 
{ 
     //Huge code unrelated to this class 
     caller.AbstractMethodA(); 
} 
} 

, а затем в AbstractClass

abstract class AbstractClass 
{ 
public abstract void AbstractMethodA(); 
public void ConcreteMethodA() 
{ 
    //Some operation 
    Helper.ConcreteMethodB(this); 
} 
} 

Edit включая интерфейс на основе развязку предложение от David Arno:

static class Helper { 
public static void ConcreteMethodB(IAbstractClass caller) 
{ 
     //Huge code unrelated to this class 
     caller.AbstractMethodA(); 
} 
} 
interface IAbstractClass { 
    void AbstractMethodA(); 
} 

а затем в AbstractClass

abstract class AbstractClass 
{ 
public abstract void AbstractMethodA(); 
public void ConcreteMethodA() 
{ 
    //Some operation 
    Helper.ConcreteMethodB(this); 
} 
} 

Это дает вам лучшую изоляцию слоев. Конечно, решение, предложенное Дэвидом в его публикации, упоминающее использование «Action» и метода передачи как аргумента, также заслуживает внимания.

+1

Я бы считать, что один шаг дальше и иметь 'ConcreteMethodB (IAbstractClass caller) и создать интерфейс, который 'AbstractClass' реализует для уменьшения связи. –

+0

@DavidArno уверен, я согласен. –

+0

О, и вам нужно изменить 'public void ConcreteMethodB ...' на 'public static void ConcreteMethodB'. Я обнаружил это при проверке того, что мой ответ (который я копирую/вставлял/редактировал с вашей) компилировал :) –

4

Чтобы полностью разъединить на две части, вы могли бы взять на себя «функциональный» по маршруту:

static class Helper 
{ 
    public static void ConcreteMethodB(Action caller) 
    { 
     //Huge code unrelated to this class 
     caller(); 
    } 
} 

Изменение AbstractClass к:

abstract class AbstractClass 
{ 
    public abstract void AbstractMethodA(); 
    public void ConcreteMethodA() 
    { 
     Helper.ConcreteMethodB(AbstractMethodA); 
    } 
} 
+0

Это потрясающе. Большое спасибо за всю помощь. Мне пришлось попробовать использовать пользовательский делегат вместо Action, так как в режиме реального времени был параметр. Есть ли лучший способ сделать это, кроме того, что я пробовал? – user1928158

+0

@ user1928158, 'Action ' может вам помочь. Это встроенный делегат для метода 'void f (T param)'. Очевидно, замените 'T' типом вашего параметра в этом случае. –

+0

Я думаю, что это более элегантное решение. Приветствия @ Дэвид Арно. – user1928158

Смежные вопросы