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

4

5 回答 5

2

您可能会切换一些东西,以便该checkName()函数在Parent类中具体化,让它进行输入有效性检查,然后调用您的子类实现的一些抽象方法来完成其余的处理。

于 2015-06-15T17:34:33.193 回答
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;
    }

}
于 2015-06-15T17:36:06.910 回答
2

大卫的回答涵盖了解决方案的症结,但没有涵盖解决方案的复杂性。其他答案(例如来自Alex 的答案)也涵盖了解决方案的一些细节,但仅限于checking作为name条件的一部分。理想的是有一个通用的解决方案,它可以适用于任何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. 我们之所以这样做doSomething final,是因为这是我们不希望子类更改的代码。我们使它public对客户端代码可见。
  2. 我们使它们只对子类可见,而对客户端代码不可见getCondtiondoSomethingOnCondition protected我们制作它们abstract以便子类可以组装条件和条件满足后要完成的工作。
  3. 使用泛型,您可以扩展您的解决方案以适用于任何数据类型,而不仅仅是String. 你所要做的就是引入一个type-parameterinParent
于 2015-06-15T18:01:40.423 回答
1

是的。在父级上添加:

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

}

并在每个孩子的电话

checkNameEquality(str);

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

abstract String getnameForClass();

并在每个孩子身上实施。

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

于 2015-06-15T17:35:03.520 回答
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。

于 2015-06-15T17:36:26.610 回答