2015-06-15 2 views
1

У меня есть ниже классов:Повторное использование условных операторов в подклассах.

public abstract class Parent { 

    public abstract boolean checkName(String str); 
} 


public class Child1 extends Parent { 

    public static final String NAME = "CHILD1"; 

    @Override 
    public boolean checkName(String str) { 
     //check input validity: 
     if (!NAME.equals(str)) { 
      throw new IllegalArgumentException("some thing"); 
     } 
     //... 
    } 
} 


public class Child2 extends Parent { 

    public static final String NAME = "CHILD2"; 

    @Override 
    public boolean checkName(String str) { 
     //check input validity: 
     if (!NAME.equals(str)) { 
      throw new IllegalArgumentException("some thing"); 
     } 
     // ... 
    } 

} 

Вы можете увидеть check input validity частей checkName методов в обеих классах same.I знают, что нет никакого способа, чтобы переместить эту совместную часть к абстрактной checkName методы родителя, но есть способ избежать повторения?

+0

Сделайте свой родительский класс не абстрактно ... и реализовать этот метод там. – River

+0

Мне 'checkName' не похоже на то, что вы должны наследовать .. Для меня это больше похоже на метод класса утилит. – hagrawal

ответ

2

Вы можете переключать вещи так, чтобы функция checkName() была конкретной в классе Parent, проведет ли она проверку достоверности ввода, а затем вызовет абстрактный метод, который реализует ваши дочерние классы для выполнения остальной части обработки.

+0

Это больше похоже на комментарий, чем на ответ. Это суть решения, которое не займет много времени, чтобы кто-то понял. Интересно, что это за тонкости. Как вы предоставляете клиенту минимальные функциональные возможности? Как вы можете найти решение, которое может быть использовано для проверки условия на любом 'String', а не только на' name'? Легче сказать, чем сделать, и, честно говоря, другие ответы помогают лучше объяснить, как это сделать. – CKing

1

Да. На материнской добавить:

protected void checkNameEquality(String str) { 
      //check input validity: 
    if (!getNameForClass().equals(str)) { 
     throw new IllegalArgumentException("some thing"); 
    } 

}

и на каждого ребенка вызова

checkNameEquality(str); 

Чтобы получить доступ к статическим имени нужно добавить еще один абстрактный метод, чтобы получить имя для этого класса.

abstract String getnameForClass(); 

и реализовать его у каждого ребенка.

Невозможно заставить разработчика выполнить эту проверку, но вам нужно только написать код один раз.

+0

Что будет 'NAME' в методе вашего родительского класса? – hagrawal

2

Сделайте это в обычном режиме. Создайте реальный метод «проверить достоверность ввода» в абстрактном классе и используйте его в любом методе ваших реальных классов. Это обычный способ, и он часто используется для рефакторинга.

Также наличие одной статической переменной для всех классов не имеет смысла. Вот что, я думаю, что вам нужно:

public abstract class Parent { 

    public String NAME; 

    public abstract boolean checkName(String str); 

    public void checkInputValidity(String str) { 
     if (!NAME.equals(str)) { 
      throw new IllegalArgumentException("some thing"); 
     } 
    } 
} 

class Child1 extends Parent { 
    public Child1() { 
     NAME = "CHILD1"; 
    } 

    @Override 
    public boolean checkName(String str) { 
     checkInputValidity(str); 
     // ... 
     return true; 
    } 
} 

class Child2 extends Parent { 

    public Child2() { 
     NAME = "CHILD2"; 
    } 

    @Override 
    public boolean checkName(String str) { 
     // check input validity: 
     checkInputValidity(str); 
     // ... 
     return true; 
    } 

} 
+0

Что заставляет клиентский код вызывать 'checkInputValidity' (поскольку это' public') и идет вразрез с намерением вашего API? Что происходит, когда подкласс хочет иметь условие в поле 'address', а не в поле' name'. См. Мой ответ для более гибкого подхода. – CKing

0

Создать метод в абстрактном классе с общей реализации и вызова пользовательских (преодолено) осуществление оттуда:

public abstract class Parent { 
    public final boolean checkName(String str) { 
     if (!getName().equals(str)) { 
      throw new IllegalArgumentException("some thing"); 
     } 

     return _checkName(str); 
    } 

    public abstract boolean _checkName(String str); 

    public abstract String getName(); 
} 


public class Child1 extends Parent { 

    public static final String NAME = "CHILD1"; 

    @Override 
    public boolean _checkName(String str) { 
     //... 
    } 

    public String getName() { 
     return NAME; 
    } 
} 


public class Child2 extends Parent { 

    public static final String NAME = "CHILD2"; 

    @Override 
    public boolean _checkName(String str) { 
     // ... 
    } 

    public String getName() { 
     return NAME; 
    } 

} 

В качестве альтернативы, вы также может вызывать родительский checkName из дочерних методов.

+0

Как «NAME» будет разрешен в конкретном методе вашего родительского класса? – hagrawal

+0

@hagrawal thanks исправлено код – 6ton

+0

Я думаю, вам нужно 'if (! GetName(). Equals (str)) {' – hagrawal

2

David's Ответ покрывает суть решения, но не охватывает тонкости решения. Другие ответы (например, номер Alex) также охватывают некоторые детали решения, но ограничиваются checkingname как часть условия. Идеально было бы иметь обобщенное решение, которое может работать для любого поля String не только для проверяя name.

Есть две части кода, которые вам нужно абстрагировать из:

  1. условие, которое должно быть выполнено Симметричного выполнить операцию
  2. выполняемую операцию, когда выполняется условие

Это то, что вы можете сделать:

public abstract class Parent { 

    public final void doSomething(String str) { 
     if(getCondition(str)) { 
      doSomethingOnCondition(str); 
     } else { 
      throw new IllegalArgumentException("some thing"); 
     } 
    } 

    protected abstract boolean getCondition(String str); 

    protected abstract void doSomethingOnCondition(String str); 


} 


class Child1 extends Parent { 

    public static final String NAME = "CHILD1"; 

    @Override 
    protected void doSomethingOnCondition(String str) { 
     System.out.println("doing something with "+str); 
    } 

    @Override 
    protected boolean getCondition(String str) { 
     return NAME.equals(str); 
    } 
} 

Клиентский код может затем просто вызвать метод doSomething следующим образом:

parent.doSomething(str); 

Пару моментов отметить:

  1. Мы doSomethingfinal, потому что это часть кода, мы не хотим, чтобы подклассы изменение. Мы делаем это public так, чтобы он был виден клиенту.
  2. Мы делаем getCondtion и doSomethingOnConditionprotected так, чтобы они были видны только для дочерних классов, а не для кода клиента. Мы делаем их abstract, чтобы дочерние классы могли собрать условие и работу, выполняемую после выполнения условия.
  3. С помощью дженериков вы можете расширить свое решение для работы с любым типом данных , а не только с String. Все, что вам нужно сделать, это ввести type-parameter в Parent
Смежные вопросы