gpt4 book ai didi

java - 安全地加强类型之间的关系

转载 作者:行者123 更新时间:2023-11-30 07:49:30 25 4
gpt4 key购买 nike

我正在构建一个系统,用于编写有关拍摄鸟类照片的人的代码(真正的系统实际上不是关于那个的,我在这里使用鸟类来代替我无法发布的业务逻辑)。我在保证我的代码类型安全的同时还强制执行我想要的所有关系并避免代码变得 super 困惑时遇到了麻烦。这是我的。

鸟分为三种

public interface BirdType {}
public class BlueJay implements BirdType {}
public class Cardinal implements BirdType {}
public class Canary implements BirdType {}

对于每一种鸟,都有一种专门为这种鸟拍照的相机,以及一种吸引这种鸟的特殊鸟叫声。

public interface BirdCamera<BT extends BirdType> {}
public interface BirdCall<BT extends BirdType> {}
public class BlueJayCamera implements BirdCamera<BlueJay> {}
public class CardinalCamera implements BirdCamera<Cardinal> {}
public class CanaryCamera implements BirdCamera<Canary> {}
public class BlueJayCall implements BirdCall<BlueJay> {}
public class CardinalCall implements BirdCall<Cardinal> {}
public class CanaryCall implements BirdCall<Canary> {}

这些部分组合在 Photographer 界面中,该界面为实现者强制了摄影师各部分之间的关​​系。

public interface Photographer 
<BT extends BirdType,
CAM extends BirdCamera<BT>,
CAL extends BirdCall<BT>>
{
CAM getPhotographersCamera();
CAL getPhotographersBirdCall();
void examineCamera(CAM camera);
}

它由三个这样的类实现,每只鸟一个:

public class BlueJayPhotographer implements Photographer<BlueJay, BlueJayCamera, BlueJayCall> {

@Override
public BlueJayCamera getPhotographersCamera() {
//Do bluejay specific logic
return new BlueJayCamera();
}

@Override
public BlueJayCall getPhotographersBirdCall() {
//Do bluejay specific logic
return new BlueJayCall();
}

@Override
public void examineCamera(BlueJayCamera camera) {
//Do bluejay specific logic
}
}

关于此的一个可取之处是它可以防止其他开发人员将来犯错误。其他人以后无法创建

public class ConfusedPhotographer implements Photographer<BlueJay, CardinalCamera, CanaryCall>

因为 Photographer 中的限制阻止了它。

当类想要使用摄影师时,他们会调用 PhotographerProvider

public class PhotographerProvider {
public Photographer get(int birdCode) {
if (birdCode == 0) {
return new BlueJayPhotographer();
}
else if (birdCode == 1) {
return new CardinalPhotographer();
}
else if (birdCode == 2) {
return new CanaryPhotographer();
}
else {
throw new IllegalArgumentException("Unsupported bird code: " + birdCode);
}
}
}

NationalPark 是我的应用程序的核心类之一,其中一个需要在其许多方法中使用摄影师的类。这是国家公园方法的示例:

  public void importantMethod(PhotographerProvider photographerProvider) {
// blah blah logic goes here
int mostCommonBirdType = 1;
Photographer typicalTourist = photographerProvider.get(mostCommonBirdType);
BirdCamera cam = typicalTourist.getPhotographersCamera();
typicalTourist.examineCamera(cam);
// blah blah more logic here
}

编译器不喜欢该方法的最后一行,并产生警告:作为原始类型“birdexample.Photographer”的成员未经检查调用“examineCamera(CAM)”

我不想要这个警告,但我找不到一种不会在其他地方引起错误的修复方法……我还想避免在我的每个类中造成巨大的困惑整个程序必须用鸟的类型、相机和叫声进行参数化。我该怎么做(除了抑制/忽略警告之外)?

最佳答案

您的具体示例可以在没有警告的情况下完成,如下所示:

Photographer<?, ?, ?> typicalTourist = photographerProvider.get(mostCommonBirdType);
foo(typicalTourist);

<BT extends BirdType,
CAM extends BirdCamera<BT>> void foo(Photographer<BT, CAM, ?> typicalTourist) {
CAM cam = typicalTourist.getPhotographersCamera();
typicalTourist.examineCamera(cam);
}

但我会警告您的设计。老实说,任何超过 1 种类型的变量都非常笨拙。 2 对于像 map 这样的情况是可以容忍的,但是 3 有点疯狂——你最终用类型声明填满了一半的行。 6(您在实际代码中所说的数字)彻底进入了憎恨自己、憎恨同事或两者的境界。

如果您真的需要这些泛型,请仔细考虑 - 如果您能摆脱它们,您可能会减轻很多眼睛疲劳。

关于java - 安全地加强类型之间的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48508820/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com