3

我需要弃用 Java SDK 中的 API 以使其更通用。但我不知道如何在以下情况下做到这一点:

public class AdoptDog {
    public interface OnDogAdoption {
        public void onDogAdoption(String dogName);
    }
    public void adoptDog(final String dogName, OnDogAdoption callbackObj) {
        // Perform asynchronous tasks...
            // Then call the callback:
            callbackObj.onDogAdoption(dogName);
    }
}

SDK用户调用如下:

AdoptDog adoptDog = new AdoptDog();
adoptDog.adoptDog("Snowball", new OnDogAdoption {
    @Override
    public void onDogAdoption(String dogName) {
        System.out.println("Welcome " + dogName);
    }
};

我想从 Dog 推广到 Pet 并弃用提及 Dog 的 API。为了向后兼容,当我弃用 API 时,上面采用 Snowball 的代码片段不必更改。

我如何尝试弃用 Dog API:

// Introduce Pet API

public class AdoptPet {
    public interface OnPetAdoption {
        public void onPetAdoption(String petName);
    }
    public void adoptPet(final String petName, OnPetAdoption callbackObj) {
        // Perform asynchronous tasks...
            // Then call the callback:
            if (callbackObj instanceof OnDogAdoption) {
                ((OnDogAdoption) callbackObj).onDogAdoption(petName);
            }
            else {
                callbackObj.onPetAdoption(petName);
            }
    }
}

// Dog API now extends Pet API for backward compatibility

@Deprecated
public class AdoptDog extends AdoptPet {
    @Deprecated
    public interface OnDogAdoption extends AdoptPet.OnPetAdoption {
        @Deprecated
        public void onDogAdoption(String dogName);
    }
    @Deprecated
    public void adoptDog(final String dogName, OnDogAdoption callbackObj) {
        super.adoptPet(dogName, callbackObj);
    }
}

问题是它不完全向后兼容。SDK 的用户必须实现 AdoptPet.OnPetAdoption.onPetAdoption() 否则会出现编译器错误:

AdoptDog adoptDog = new AdoptDog();
adoptDog.adoptDog("Snowball", new OnDogAdoption {
    @Override
    public void onDogAdoption(String dogName) {
        System.out.println("Welcome " + dogName);
    }

    // PROBLEM: How avoid customers having to implement this dummy method? 
    @Override
    public void onPetAdoption(String petName) {
        assert("This code should not be reached");
    }
};

是否有其他方法可以弃用AdoptDog(特别是OnDogAdoption)并保持完全的向后兼容性?

4

2 回答 2

5

Java 8 允许您指定default方法实现。您可以使用它来帮助您,例如:

@Deprecated
public interface OnDogAdoption extends AdoptPet.OnPetAdoption {
    @Deprecated
    void onDogAdoption(String dogName);

    default void onPetAdoption(String petName) {
        onDogAdoption(petName);
    }
}

通过具有默认实现,客户端代码将不需要实现它(但如果他们愿意,可以),因此不应该有编译错误。


注意: 所有接口方法都是public默认的——事实上它们只能是public——不需要指定。

于 2018-05-09T21:06:22.050 回答
3

你不扩展OnPetAdoption. AOnDogAdoption不是OnPetAdoption. AOnPetAdoption还可以处理猫的收养。一个OnDogAdoption不能。

我建议您将其包装OnDogAdoption在 a 中OnDogAdoptionDispatcher,并使用该调度程序调用新方法,例如:

@Deprecated
public class AdoptDog extends AdoptPet {
    @Deprecated
    public interface OnDogAdoption {
        @Deprecated
        public void onDogAdoption(String dogName);
    }

    private static class DogAdoptionDispatcher implements AdoptPet.OnPetAdoption {
            final OnDogAdoption target;
            public DogAdoptionDispatcher(OnDogAdoption target) {
                this.target = target;
            }
            @Override
            public void onPetAdoption(String petName) {
                target.onDogAdoption(petName);
            }
    }

    @Deprecated
    public void adoptDog(final String dogName, OnDogAdoption callbackObj) {
        super.adoptPet(dogName, new DogAdoptionDispatcher(callbackObj));
    }
}

这样,您仍然具有向后兼容性和干净的新界面。

如果您使用的是 Java 8 或更高版本,则不需要单独的类,您可以这样做

public void adoptDog(final String dogName, OnDogAdoption callbackObj) {
    super.adoptPet(dogName, callbackObj::onDogAdoption);
}
于 2018-05-09T21:36:12.787 回答