在子类中重用条件语句。

时间:2015-06-15 17:31:29

标签: java abstract dry abstract-methods

我有以下课程:

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 validitycheckName个方法的部分是相同的。我知道没有办法将这个联合部分移动到父级的抽象checkName方法,但是在那里一种避免这种重复的方法?

5 个答案:

答案 0 :(得分:2)

你可以切换一下,以便checkName()类中的Parent函数是具体的,让它进行输入有效性检查,然后调用你的子类实现其余的一些抽象方法处理。

答案 1 :(得分: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;
    }

}

答案 2 :(得分:2)

David's回答涵盖解决方案的关键,但不包括解决方案的复杂性。其他答案(例如来自Alex)的答案也涵盖了解决方案的一些细节,但仅限于checking name作为条件的一部分。理想的是拥有一个可用于任何String字段的通用解决方案,不仅可用于检查name

您需要抽象出代码的两个部分:

  1. 执行操作必须满足的条件
  2. 满足条件时执行的操作
  3. 这是你可以做的:

    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. 我们制作doSomething final,因为这是我们不希望子类发生变化的代码段。我们将其设为public,以便客户端代码可以看到它。
    2. 我们制作getCondtiondoSomethingOnCondition protected,以便它们仅对子类可见,而不是客户端代码。我们将它们设为abstract,以便子类可以在条件满足后组合条件和要完成的工作。
    3. 使用泛型,您可以将解决方案扩展到任何工作 数据类型而不仅仅是String。你所要做的就是介绍 type-parameter
    4. 中的Parent

答案 3 :(得分:1)

是。在父级上添加:

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

}

和每个孩子的电话

checkNameEquality(str);

要访问静态名称,您需要添加另一个抽象方法来获取该类的名称。

abstract String getnameForClass();

并在每个孩子中实施。

没有办法强制实现者进行检查,但你只需要编写一次代码。

答案 4 :(得分: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。