如何使用不在父类中的常用方法处理子类?

时间:2014-05-08 18:01:16

标签: java

我有以下自动生成的代码:

编辑:它是自动生成的,所以我不允许修改它。 (如果只是那么容易......)

    abstract class Foo {

    }

    class Fuwa extends Foo {
            String chocolate() {...}

            String muffin() {...}
    }

    class Fuko extends Foo {
            String chocolate() {...}

            String cookie() {...}
    }

两个子类中的chocolate()方法实际上(除了变量名称之外)逐行相同且基本上是可控制的。

根据客户端输入,我想测试Foo的指定子项并验证响应。目前我有:

    class FooFactory {
            Foo createFoo(name) {
                    if (name.equals("fuwa")) {
                            ...
                            // returns a Fuwa object
                    } else if (name.equals("fuko")) {
                            ...
                            // returns Fuko object
                    }
            }
    }


    class MuffinTester extends FooTester {
            boolean test(Foo inputFoo) {
                    Result x = ((Fuwa) inputFoo).muffin();
                    return validate(x);
            }
            private validate(x) {...}
    }

    class CookieTester extends FooTester {
            boolean test(Foo inputFoo) {
                    Result x = ((Fuko) inputFoo).cookie();
                    return validate(x);
            }
            private validate(x) {...}
    }

    class TesterFactory {
            FooTester createTest(name) {
                    if (name.equals("muffin")) {
                            ...
                            // returns MuffinTester object
                    } else if (name.equals("cookie")) {
                            ...
                            // returns CookieTester object
                    } else if (name.equals("chocolate")) {
                            ...
                            // returns ChocolateTester object
                    }
            }
    }

客户端指定要测试的Foo和方法,并且FooFactory和TestFactory(分别)实例化所需的对象(有逻辑来确保请求有效并且Foo包含方法,例如没有测试cookie()在福娃)。

当我尝试编写ChocolateTester时会出现问题:

    class ChocolateTester extends FooTester {
            boolean test(Foo inputFoo) {
                    Result x = ((???) inputFoo).chocolate();
                    return validate(x);
            }
            private validate(x) {...}
    }

我不能将inputFoo保留为Foo,因为编译器不喜欢它没有chocolate()方法。而且我无法将输入输入Fuwa或Fuko,因为无论哪一个我都没有把它投入使他们对他们的兄弟姐妹感到困惑(尽管他们在所有意图和目的下暴露于巧克力时都是相同的)。如果我可以修改Foo会很棒,但由于它是自动生成的,所以我无法触摸它。

我能想到的最好的是一堆if / else语句:

    class ChocolateTester extends FooTester {
            boolean test(Foo inputFoo) {
                    Result x;
                    if (inputFoo instanceof Fuwa) {
                            x = ((Fuwa) inputFoo).chocolate();
                    } else if (inputFoo instanceof Fuko) {
                            x = ((Fuko) inputFoo).chocolate();
                    }
                    return validate(x);
            }
            private validate(x) {...}
    }

但是当有大约15个Foo并且我必须复制巨型if / else块以用于其他方法时,孩子Foo有一个共同点,比如一个cake()方法,感觉非常hacky。此外,当一个名为Futaro的新Foo加入时,这听起来像维护噩梦,我不仅要更新FooFactory中的if / else块,还要更新ChocolateTester和CakeTester以及任何其他常用方法。

因此...

我很遗憾被啰嗦,但基本上我想问有没有更好的方法来做到这一点(这不是太hacky /不可维护)?是否有一个简单的注释来强制方法调用不存在的方法,或者将对象强制转换为实际类型,或者使用反射来解决这个问题?

更新:我最终决定在方法调用中使用反射see below

3 个答案:

答案 0 :(得分:2)

是的!

您可以在Foo中创建抽象方法,如下所示:

abstract class Foo {
        abstract String Chocolate();
}

或者你把Foo变成了一个接口,迫使任何实现类都有一个chocolate()方法:

 interface Foo {
        String chocolate();
}

class Fuwa implements Foo {
        String chocolate() {...}

        String muffin() {...}
}

class Fuko implements Foo {
        String chocolate() {...}

        String cookie() {...}
}

答案 1 :(得分:0)

自动生成代码后,您可以对其进行后处理,以便为子类添加合适的接口。您用来执行此操作的确切方法取决于您已经使用的构建自动化。例如,如果您使用ant来运行axis2代码生成器,那么可以直接向代码生成目标添加一些额外的步骤来更改每个生成的文件。< / p>

答案 2 :(得分:0)

我向老板提出了这个问题,他建议我使用反射来调用方法。

所以在这种情况下:

    class ChocolateTester extends FooTester {
            boolean test(Foo inputFoo) {
                    Method chocolateMethod = inputFoo.getClass().getMethod("chocolate");
                    Result x = chocolateMethod.invoke(inputFoo);
                    return validate(x);
            }
            private validate(x) {...}
    }

我需要添加一些代码验证inputFoo确实有一个chocolate()方法并捕获所有异常,但这似乎是给定约束的最佳解决方案,我无法修改自动生成的代码。