簡體   English   中英

創建Java子類的層次結構

[英]Creating a hierarchy of Java subclasses

我正在嘗試在java中設置位置的層次結構。 一個地方可以大也可以小,更大的地方包括較小的子位置。 因此,世界包含國家,國家包含城市,依此類推,直到建築物和房間。

我創建了一個名為Place的抽象類,它是所有這些類型的父類。 每個地方都包含一個子位置圖,一個父位置以及獲取父子位置(也就是一個鄰居)的功能。

我遇到的主要問題是,父母的子位置應該是某人的類的實例,但是無法用java來指定。

我已經考慮過對所有類型進行硬編碼,因此City的getParent返回一個Country,而getSublocations返回一個Building Graph,但是這在更改類的功能或添加新類方面造成了一些問題,並且涉及大量的代碼復制。 還有其他解決方法嗎?

編輯:

感謝所有的答案。 到目前為止,這就是我所擁有的。 這不是完美的,但也不錯。 我唯一要復制的代碼是getNeighbors()的實現。 它曾經直接在抽象類(this.getParent()。getSublocations()。getEdges(this))中實現,但這只是一行代碼。

import java.util.HashSet;
public abstract class Place {
    //World, Region, City, Building, Room
    public enum Direction {
        East, Northeast, North, Northwest, West, Southwest, South, Southeast, Invalid;
        public static Direction fromInt(int i) {
            switch (i) {
            case 0: return East;
            case 1: return Northeast;
            case 2: return North;
            case 3: return Northwest;
            case 4: return West;
            case 5: return Southwest;
            case 6: return South;
            case 7: return Southeast;
            default: return Invalid;
            }
        }
        public static Direction fromAngle(double angle) {
            return fromInt((int) (angle+22.5)/45);
        }
    }

    protected final int locked = Integer.MAX_VALUE;
    protected int x, y; //longitude and latitude
    public abstract String getName();
    public abstract <S extends Place> Graph<S> getSublocations();
    public abstract <T extends Place> T getParent();
    public abstract <U extends Place> HashSet<Passage<U>> getNeighbors();

    public final Direction getDirection(Place otherPlace) {
        if (otherPlace == null) {
            return Direction.Invalid;
        } else if (this.getClass() == otherPlace.getClass()) {
            return Direction.fromAngle(Math.atan2(otherPlace.y-y, otherPlace.x-x));
        } else {
            return Direction.Invalid;
        }
    }
}

我已經遇到過幾次這個問題,當您遇到類似這樣的問題時,我不建議您在這種情況下使用泛型,因為您已經知道每個地方將要返回的內容。 希望這段代碼會有所幫助。

public interface Place {
    // Place can be an abstract class if you want. 
    // Making it abstract could cause some problems because it might make you use generics
    // I recommend an interface
    List<? extends Place> getSublocations();
    Place getParent();
}
public class World implements Place {

    private List<Country> countries;

    @Override
    public List<Country> getSublocations() {
        return this.countries;
    }

    @Override
    public Place getParent() {
        return null;
    }
}
public class Country implements Place {
    private List<City> cities;
    private World parent;

    @Override
    public List<City> getSublocations() {
        return this.cities;
    }

    @Override
    public World getParent() {
        return this.parent;
    }
}
public class City implements Place {
    private Country parent;

    @Override
    public List<? extends Place> getSublocations() {
        return null;
    }

    @Override
    public Country getParent() {
        return this.parent;
    }
}

在代碼中不應有太多的復制和粘貼,但是我認為這是您的最佳選擇。

假設每種類型都直接從Place擴展(與City extends Country ,這是錯誤的),那么您應該能夠使用泛型來限制樣板,例如:

public class Place<P extends Place<?, ?>, C extends Place<?, ?>> {
  // ...
  public final P getParent() { ... }
  public final Set<C> getChildren() { ... }
}

public class City extends Place<Country, Building> { ... )

但是,實際上,您可能會發現,在兩種情況下都簡單地返回Place ,並且避免在類型系統中硬編碼層次結構的不同級別之間的關系,會更靈活。 如果事情發生了變化(例如,您在“ Country和“ City之間引入了State類型),則必須更正依賴於先前關系的每個呼叫站點。

看一下復合圖案,也許使用一些標記界面。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM