两个互相引用的通用接口

时间:2018-12-28 12:42:13

标签: java generics

我正在尝试编写两个通用的类/接口Tile(interface Tile<S extends Side<? extends Tile<S>>>)和Side(abstract class Side<T extends Tile<? extends Side<T>>>),其中一个接口的通用类型引用了另一个接口。

现在,当我尝试像这样实现Tile接口时:

public abstract class TileImpl<S> implements Tile<S extends Side<? extends Tile<S>>

我必须继续写S类型的边界:

S extends Side<? extends Tile<S>>

如何使此代码正常工作?

public interface Tile<S extends Side<? extends Tile<S>>> {

    S getSide(Direction d);

    /**
     * Returns true if the current instance of Tile and the Tile t
     * fit together.
     * @param t a tile adjacent to the current tile
     * @param d the position of the tile t with respect to the current tile
     * @return true if the current tile and the tile t fit together
     */
    boolean fitsWith(Tile<S> t, Direction d);
}

public abstract class Side<T extends Tile<? extends Side<T>>> {
    private final T parent;

    public Side(T parent) {
        this.parent = parent; 
    }

    public T getParent() {
        return parent;
    }
}

1 个答案:

答案 0 :(得分:0)

public abstract class TileImpl<S> implements Tile<S extends Side<? extends Tile<S>>

您的问题是,您在S上设置了界线,而在public abstract class TileImpl<S extends Side<? extends Tile<S>>> implements Tile<S> 上没有使用它。因此,只需将边界移到正确的位置即可。

   /**
 * Defines a {@link LiveData} object that wraps a {@link Publisher}.
 *
 * <p>
 * When the LiveData becomes active, it subscribes to the emissions from the Publisher.
 *
 * <p>
 * When the LiveData becomes inactive, the subscription is cleared.
 * LiveData holds the last value emitted by the Publisher when the LiveData was active.
 * <p>
 * Therefore, in the case of a hot RxJava Observable, when a new LiveData {@link Observer} is
 * added, it will automatically notify with the last value held in LiveData,
 * which might not be the last value emitted by the Publisher.
 *
 * <p>
 * Note that LiveData does NOT handle errors and it expects that errors are treated as states
 * in the data that's held. In case of an error being emitted by the publisher, an error will
 * be propagated to the main thread and the app will crash.
 *
 * @param <T> The type of data hold by this instance.
 */
private static class PublisherLiveData<T> extends LiveData<T> {
    private final Publisher<T> mPublisher;
    final AtomicReference<LiveDataSubscriber> mSubscriber;

    PublisherLiveData(@NonNull Publisher<T> publisher) {
        mPublisher = publisher;
        mSubscriber = new AtomicReference<>();
    }

    @Override
    protected void onActive() { // Problem
        super.onActive();
        LiveDataSubscriber s = new LiveDataSubscriber();
        mSubscriber.set(s);
        mPublisher.subscribe(s);
    }

    @Override
    protected void onInactive() { // Problem
        super.onInactive();
        LiveDataSubscriber s = mSubscriber.getAndSet(null);
        if (s != null) {
            s.cancelSubscription();
        }
    }

    final class LiveDataSubscriber extends AtomicReference<Subscription>
            implements Subscriber<T> {

        @Override
        public void onSubscribe(Subscription s) {
            if (compareAndSet(null, s)) {
                s.request(Long.MAX_VALUE);
            } else {
                s.cancel();
            }
        }

        @Override
        public void onNext(T item) {
            postValue(item);
        }

        @Override
        public void onError(final Throwable ex) {
            mSubscriber.compareAndSet(this, null);

            ArchTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
                @Override
                public void run() {
                    // Errors should be handled upstream, so propagate as a crash.
                    throw new RuntimeException("LiveData does not handle errors. Errors from "
                            + "publishers should be handled upstream and propagated as "
                            + "state", ex);
                }
            });
        }

        @Override
        public void onComplete() {
            mSubscriber.compareAndSet(this, null);
        }

        public void cancelSubscription() {
            Subscription s = get();
            if (s != null) {
                s.cancel();
            }
        }
    }
}
相关问题