Как реализовать интерфейс, чьи два экземпляра могут зависеть друг от друга, в скелетной реализации, то есть в классе, без понижения? - PullRequest
3 голосов
/ 31 марта 2020

Учитывая Person интерфейс:

public interface Person {
    Person getSpouse();
    void marry(Person spouse);
}

Я сделал скелетную реализацию :

public abstract class AbstractPerson implements Person {
    private Person spouse;
    @Override
    public Person getSpouse() {
        return spouse;
    }
    @Override
    public void marry(Person spouse) {
        this.spouse = spouse;
        ((MarriedPerson) spouse).setSpouse(this);//forced to downcast
    }
    protected void setSpouse(Person spouse) {
        this.spouse = spouse;
    }
}

Недостаток вызова marry(Person spouse) с скелетная реализация является аргументом spouse должен быть экземпляром AbstractPerson. Однако, если spouse.marry(this) вызывается внутри marry(), он будет бесконечно l oop и завершится с ошибкой переполнения стека

Вопрос: возможно ли осуществить брак (лицо супруга) без принижения? как?

Ответы [ 2 ]

4 голосов
/ 01 апреля 2020

Вы слишком много думаете. Ваша ошибка в том, что у вас есть Person интерфейс, MarriedPerson и AbstractPerson классы. Сам факт вступления в брак не меняет вашу «индивидуальность», поэтому он не должен преобразовывать экземпляр в другой класс (ie MarriedPerson). Скорее, он изменяет состояние экземпляра, так что isMarried() будет истинным.

Удалите лот и получите один класс:

public class Person {
    private Person spouse;  // getters/setters not shown

    public boolean isMarried() {
        return spouse != null;
    }

    public void marry(Person spouse) {
        this.spouse = spouse;
        spouse.spouse = this;
    }

    public void divorce() {
        this.spouse = null;
        spouse.spouse = null;
    }
}

Примечание:

Более универсально точная модель будет иметь List<Person> spouces, так как некоторые страны допускают супружеских супругов. Пол также вступает в игру, поскольку эти страны, как правило, разрешают мужчинам иметь нескольких супругов, и все эти супруги должны быть женщинами (однополые браки запрещены во многих странах), поэтому класс Man будет иметь List<Female> и Female будут иметь Man spouse.
Не называть женскую версию Woman было преднамеренным, так как в некоторых странах брак женщины допускается до достижения ими половой зрелости, и поэтому технически не будет классифицироваться как женщина.

0 голосов
/ 16 апреля 2020

Вы можете рассмотреть совокупную коллекцию подклассов Mix-In класса PeronAttribute (или реализует интерфейс PersonAttribute). Это похоже на реализацию Java LDAP Attribute / BasicAttribute, которая позволяет динамически c расширять как поведение, так и структурные характеристики. Традиционные ОО (java / C ++) склоняются к тому, что я называю «stati c иерархии классов». Они хороши с точки зрения проверки во время компиляции (по сравнению с задержками во время выполнения) и легко моделируются в UML, потому что определения классов похожи на DDL (чтобы провести параллель с RDBMS и таблицами). Этот подход устраняет разрыв с более динамичными c языками, такими как JavaScript (см .: рост NodeJS и реинкарнация Netscape LiveWire с конца 1990-х годов)

Ссылка на LDAP: https://docs.oracle.com/javase/7/docs/api/javax/naming/directory/Attribute.html

Ссылка GoF: https://martinfowler.com/bliki/GangOfFour.html https://martinfowler.com/eaaCatalog/ шаблоны: поведенческие, структурные, творческие

Ссылка Livewire (1997): https://www.drdobbs.com/database/livewire-web-to-database-solutions-part/184410393 https://cs.nyu.edu/~yap/html/tutorial/getstart.htm

...