2011-07-14 15 views
12

Po nadpisaniu metody należy zachować podpis metody i nie można zmniejszyć jej widoczności. Teraz próbowałem tego, co się dzieje, gdy robię to z atrybutami. Byłem zaskoczony - TO DZIAŁA! Spójrz siebie:Zastąpienie atrybutów

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

} 

Więc to jest możliwe napisanie atrybut w podklasie o tej samej nazwie attibute jak w nadrzędnej, ale można użyć innego widoczność (modyfikator) i typ. Powiedziałbym więc, że atrybuty w nadklasie i podklasie są prawie całkowicie niezależne od siebie.

Teraz, jeśli naprawdę używasz tej samej nazwy atrybutu w nadklasie i podklasie, skutecznie ukrywasz atrybut nadklasy. Podczas uzyskiwania dostępu do atrybutu przy użyciu podklasy uzyskuje się atrybut podklasy. Ale atrybut superklasy również istnieje! Aby uzyskać dostęp do atrybutu nadklasy z zewnątrz, musisz wykonać rzutowanie. Od wewnątrz słowo kluczowe "super" powinno być użyteczne.

Pytanie 1: Teraz zasadniczo masz dwa różne atrybuty o tej samej nazwie. Czy to nie przełamuje LSP?

Po co doszedłem do tego szczegółu: Eksperymentuję z autorskim schematem wytrwałości. Chcę przeczytać pełny wewnętrzny stan obiektu i utrzymywać ten stan. Odczytuję wszystkie wartości atrybutu poprzez odbicie, zaczynając od podtypu i przechodząc przez nadklasy. Teraz, jeśli istnieją dwa atrybuty o tej samej nazwie w nadklasie i podklasie, muszę pamiętać klasę, która deklaruje atrybut, aby móc odwzorować wartości atrybutów na odpowiednie atrybuty i przywrócić stan obiektu.

Pytanie 2: Jakieś inne pomysły jak sobie z tym poradzić? Pytanie 3: W jaki sposób inne struktury wytrwałości obsługują ten szczegół?

Nigdy nie widziałem tego szczegółu w użyciu. Być może pisanie dwóch atrybutów o tej samej nazwie jest nieco brzydkie, ale jest to możliwe, a każda struktura uporczywości może zostać z nim skonfrontowana. Być może są sytuacje, w których ta technika może być przydatna.

Z góry.

+0

Thx do wszystkich odbierających. – anonymous

Odpowiedz

5

ORM zwykle używają standardu javabeans, który definiuje "właściwości". Właściwości definiuje raczej metoda czytnika i/lub pisarza niż pole, które odczytuje/zapisuje. W 99% przypadków właściwości to field + getter & ustawiające, ale nie musi tak być. ORM odczytuje te właściwości i wykrywa tylko te zmienne, które mają setery pobierające &. Ponieważ metody są nadpisywane, a nie zacienione, problem znika.

Jest to bardziej problem enkapsulacji niż naruszenie LSP. Dostęp do pola nie jest zależny od polimorfizmu, więc jeśli masz Foo foo = new FooSubclas(); foo.field the value of the pole Foo `będzie brane, co oznacza, że ​​zachowanie się nie zmieni.

+0

Nie lubię być związany ze specyfikacją fasoli ze względu na jej ograniczenia. To jeden z powodów, dla których zdecydowałem się spróbować swoich własnych systemów wytrwałości. Teraz mam do czynienia z niektórymi problemami, których uniknięto za pomocą innych istniejących tylko fasoli. Myślę, że muszę po prostu rozszerzyć mój model meta, aby lepiej reprezentować dziedziczenie. – anonymous

2

Pytanie 1: Nie łamie LSP, ponieważ zmienne składowe nie są polimorficzne.

1

Pytanie 1: LSP ma około behavioral subtyping i powiedziałbym, że posiadanie dwóch członków o tej samej nazwie nie zmienia samego zachowania.

Pytanie 2: Wykryj (musisz mimo to zeskanować hierarchię klas) i nie pozwalaj na to.

1

Pytanie 2: Tylko serializować/deserializować za pomocą modułów pobierających/ustawiających.

Pytanie 3: Patrz odpowiedź 2.

1

Nie można nadpisać atrybut tylko ukryć. To jest dosłownie nazywane ukrywaniem pól w tutorial. Więcej szczegółów na temat tego blog.

Q1: Nie, nie łamie LSP, wszelkie odniesienia do A a = new B(); a.myAttribute będą nadal odnosić się do A.myAttribute, a nie do B.myAttribute.

Q2: Próbowałbym tego uniknąć, ale jeśli musisz, możesz uzyskać dostęp do A.myAttribute z B, używając słowa kluczowego super.myAttribute.

Pytanie 3: Myślę, że C# pozwala na to samo, używają one base zamiast super, ale nie mam pod ręką żadnego kompilatora C#, a dokumentacja ukrywania pola w C# jest rzadka.

Powiązane problemy