覆盖属性

2022-09-04 03:45:30

重写方法时,必须保留该方法的签名,并且不能降低其可见性。现在,我尝试了使用属性执行此操作时发生的情况。我很惊讶 - 它的工作原理!看看你自己:

public class A {

    public Integer myAttribute;

}

public class B extends A {

    public String myAttribute;

}

public class Main {

        public static void main(String[] args) {
        B b = new B();
        b.myAttribute = "myString";
        ((A) b).myAttribute = 1337;
        System.out.println(b.myAttribute);
        System.out.println(((A)b).myAttribute);
    }

}

因此,可以在子类中编写与超类中具有相同 attibute 名称的属性,但您可以使用不同的可见性(修饰符)和类型。所以我想说的是,超类和子类中的属性几乎完全相互依赖。

现在,如果您确实在超类和子类中使用相同的属性名称,则可以有效地隐藏超类的属性。使用子类访问属性时,您将获得子类的属性。但是超类的属性也在那里!您必须执行强制转换才能从外部访问超类的属性。从内部看,“超级”关键字应该是有用的。

问题1:现在基本上你有两个具有相同名称的不同属性。这不会破坏 LSP 吗

为什么我会想到这个细节:我正在尝试一个自我编写的持久性框架。我想读取对象的完整内部状态并保留该状态。我通过反身读取所有属性的值,从子类型开始遍历超类。现在,如果在超类和子类中有两个具有相同名称的属性,我必须记住声明属性的类,以便能够将属性值映射到正确的属性并恢复对象的状态。

问题2:如何处理这个细节的任何其他想法?问题 3:其他持久性框架如何处理此细节?

我从未在使用中看到过这个细节。也许用相同的名称编写两个属性有点丑陋,但这是可能的,任何持久性框架都可能遇到它。也许在某些情况下,这种技术可能是有用的。

提前。


答案 1

ORMs通常使用javabeans标准来定义“属性”。属性由读取器和/或写入器方法定义,而不是由它们读取/写入的字段定义。在99%的情况下,属性是field+getter&setter,但事实并非如此。ORM 读取这些属性,并仅检测具有 getters&setter 的字段。由于方法被覆盖而不是阴影,因此问题就消失了。

这与其说是违反 LSP,不如说是封装问题。字段访问不受多态性的影响,因此,如果您具有 foo.fieldFoo,则将采用字段,这意味着行为不会改变。Foo foo = new FooSubclas();the value of the


答案 2

问题 1:它不会破坏 LSP,因为成员变量不是多态的。


推荐