【问题标题】:Java - subclass validation design patternJava - 子类验证设计模式
【发布时间】:2012-02-10 10:10:29
【问题描述】:

我有一个基类C,其中包含XYZ 字段。

C1 扩展了C 并且有一个额外的字段T

C1 构造函数中,我使用XYZ 字段的一些硬编码值调用了超级(C) 构造函数。然后我设置T

是否有任何模式可以通过在 C 构造函数中执行某些操作来自动验证 C1 的所有字段?所以我正在尝试将自动验证推送到基类。

请注意,调用超级构造函数应该在C1 构造函数中的任何语句之前完成。我从一些抽象的validate() 方法开始,但我不是我在正确的轨道上。

谢谢。

【问题讨论】:

    标签: java validation design-patterns


    【解决方案1】:

    原则上,C 不应该知道 C1 的属性,因为 C1 是 C 的特化。但是,你可以做的是在 C 中创建一个抽象的 validate() 方法,必须由 C1 实现。然后,在 C 的构造函数中,就可以调用抽象方法了。因为,C1 必须实现 validate(),然后它可以在那里添加它的属性/字段验证。

    【讨论】:

    • 是的,但在这种情况下,将在设置 T 属性之前调用 C1 验证。这是因为,我确实提到过,super() 调用必须是第一条语句。
    • 在这种情况下,您不能在调用 C 构造函数时自动验证,对吗?那么你就剩下让 C1 验证它自己添加到类层次结构中的属性了。
    • 我认为这行不通。如果不知道有哪些参数,基类应该如何验证参数?在扩展课上做这件事有那么大吗?
    • 也许如果您描述您尝试编程的实际场景,我们可以帮助建议一个好的模式。但作为一般原则,您不希望 C 了解 C1。如果 C1 'is-a' C,那么它必须是一个特化。如果不是专精,就是同一个类。
    • @guitarflow 是的,这就是为什么抽象方法被子类强制实现的原因。然后,子类对其属性的验证在子类中完成。
    【解决方案2】:

    虽然它违反了所有 OO 原则,但您可以利用 Java 的反射属性。通过反射你可以找出一个类有哪些方法和字段。因此,您可以将子类对象传递给基类,而基类可以检查所有字段并验证它们。如果你在子类构造函数的末尾这样做,你可以让验证方法返回一个值来查看这些值是否有效。

    我想说我不认为这是正确的方法,但它应该有效

    【讨论】:

    • “不是正确的方法” - 是的,但它会起作用。语言中没有任何东西可以禁止愚蠢。
    • 最终会的。我不保证会。我突然想到,如果您从构造函数中调用一个方法,并将“this”传递给该方法,我不确定这是否有效,因为对象最终尚未完全创建。所以这可能是空的。试试看,然后回到这里,这样我们就知道它是否有效。谢谢
    【解决方案3】:

    我会说超类应该验证自己。一个对象需要执行它自己的契约。 C 值的任何验证都应在其自己的构造函数中完成。同样,子类应该验证自己。

    public class A {
        private int x;
    
        public A(int x) {
            if (x < 0) throw new IllegalArgumentException("x cannot be negative");
            this.x = x;
        }
    }
    
    public class B extends A {
        private String y;
    
        public B(int x, String y) {
            super(x);
            if (y == null) throw new IllegalArgumentException("y cannot be null");
            this.y = y;
        }
    }
    

    【讨论】:

    • 所以没有办法自动从A调用一个在B中实现的方法,就在B的构造函数的末尾……对吧?
    • 不,A 根本不应该知道它是子类。那个代码不属于 B。你会要求一个类具有洞察力并预测未来:“六个月后,Freddy 将继承我。我最好准备好将他的类的验证调用放入我的东西。”疯了。
    • A不认识B所以不可能
    • 但是 A 可以提供一个抽象方法...看来我们不能在我想要的时候调用它。
    • 抱歉,在各个方面仍然是错误的。你为什么要坚持这个?将验证放在它所属的地方并完成。
    【解决方案4】:
    class C{
        Object x, y, z;
        public C(Object x, Object y, Object z){
            this.x = x;
            this.y = y;
            this.z = z;
        }
        public boolean validate(){ /**do stuff**/}
    }
    
    class D{
        public D(/**args**/){
            super(/**args**/);
            if(validate()){
                /**do stuff**//
            }
        }
    }
    

    【讨论】:

    • 正如我所提到的,我想将验证推送到基类,以自动方式进行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多