开发者

Override attributes

When you override a method you must keep the method's signature and can't reduce its visibility. Now I tried what happends when I do this with attributes. I was surprised - IT WORKS! Look yourself:

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);
    }

}

So it is possible to write an attribute in a subclass with the same attibute name as in the superclass, but you can use different visibility (modifier) and type. So I would say that the attributes in superclass and subclass are almost completely independend from each other.

Now if you really use the same attribute name in superclass and subclass you effectively hid开发者_如何学编程e the superclass's attribute. When accessing the attribute using the subclass, you get the subclass's attribute. But the superclass's attribute is there, too! You have to perform a cast to access the superclass's attribute from outside. From inside the "super" keyword should be usefull.

Question 1: Now basically you have two different attributes with the same name. Doesn't this break LSP?

Why I came to this detail is this: I am experimenting with an self written persistence framework. I want to read the complete internal state of an object and persist that state. I read all attribute's values via reflexion, starting at the subtype and traversing over the superclasses. Now if there are two attributes with the same name in superclass and subclass I have to remember the class which declares an attribute to be able to map the attributes values to the right attributes and restore an object's state.

Question 2: Any other ideas how to deal with this detail? Question 3: How do other persistence frameworks handle this detail?

I never saw this detail in use. Maybe writing two attributes with the same name is a bit ugly, but it is possible and any persistence framework may be confronted with it. Maybe there are situations where this technique might be usefull.

Thans in advance.


ORMs usually use the javabeans standard which defines "properties". Properties are defined by a reader and/or writer method rather than the field they read/write. In 99% of the cases properties are field+getter&setter, but it need not be the case. And the ORM reads these properties, and detects only the fields that have getters&setters. Since methods are overridden rather than shadowed, the problem is gone.

This is more a problem of encapsulation than a violation of LSP. Field access is not affected by polymorphism, so if you have Foo foo = new FooSubclas();foo.fieldthe value of theFoo` field will be taken, which means the behaviour won't change.


Question 1: It doesn't break LSP, because member variables are not polymorphic.


You can not override a attribute, only hide it. This is literally called hiding fields in the tutorial. More details on this blog.

Q1: No, it doesn't break LSP, any reference to A a = new B(); a.myAttribute will still refer to A.myAttribute and not to B.myAttribute.

Q2: I would try to avoid it, but if you must, you can still access A.myAttribute from B using the super.myAttribute keyword.

Q3: I think C# allows the same, they use base instead of super, but it i got no C# compiler at hand, and the documentation on field hiding in C# is sparse.


Question 1: LSP is about behavioral subtyping and I'd say having two members with the same name doesn't change behavior itself.

Question 2: Detect it (you'd need to scan the class hierarchy anyways) and don't allow it.


Question 2: Only serialize/deserialize through getters/setters.

Question 3: See answer 2.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜