gpt4 book ai didi

java - 如何正确返回从类扩展并实现接口(interface)的东西?

转载 作者:搜寻专家 更新时间:2023-11-01 02:27:04 24 4
gpt4 key购买 nike

背景

此问题适用于 Java 和 Android 开发人员。

在 Android 上,我想要一个返回从 View 扩展的东西的函数并实现 Checkable ,两者都是 Android API 的一部分。

我尝试过的

在这里和 Internet 上的其他地方搜索了一下之后,我找到了这个解决方案:

private <T extends View & Checkable> T get() {
return (T) mView;
}

请注意,mView 是扩展 View 的任何类型(并且有很多),但我保证它实现了 Checkable,因为只有那些类型才能存在。

这显示了“类型安全:未经检查的从 View 到 T 的转换”警告,但这不是问题所在。问题是我不能正确使用这个方法,例如:

View v=get(); //this works fine
Checkable c=get(); // this shows error

第二行显示错误:

Bound mismatch: The generic method get() of type ... is not applicable for the arguments (). The inferred type Checkable&View is not a valid substitute for the bounded parameter

所以我尝试使用 ","而不是 "&"。同样的错误。

但是,当我使用“,”并颠倒顺序时,我收到警告“类型参数 View 正在隐藏类型 View”,并且这两行都工作正常。

这是代码:

private <T extends Checkable, View> T get() {
return null;
}

private void foo() {
final View v = get(); // this works fine
final Checkable c = get();// this works fine too
}

但是,当我将返回的类型发送给其他函数时,它们不会将类型本身作为扩展类和接口(interface)的东西,并且始终需要转换(到 View )。

问题

正确的做法是什么?

如果我最后展示的方式是正确的,为什么我会收到警告?如果总是最多扩展一个类,为什么顺序很重要?

最佳答案

在我深入研究泛型之前......为什么不直接引入 CheckableView 并返回该类型?

public class CheckableView extends View implements Checkable {
}


private CheckableView getCheckableView() {
return checkableView;
}

如果 View 是一个接口(interface),它会工作:

interface View {}
interface Checkable {}
class CheckableView implements Checkable, View {}

public class Main {

private static CheckableView checkableView;

private static <T extends View & Checkable> T get() {
return (T) checkableView;
}

public static void main(String[] args) {
View view = Main.get();
Checkable checkable = Main.get();
}
}

我认为理解泛型的问题在于,T extends View & Checkable 在实际情况下并不意味着你可以返回任何扩展 View 并实现 可检查

这意味着客户端可以将返回的类型转换为任何扩展 View 并实现 Checkable 的类型。

客户可以这样做:

class CheckableView extends View implements Checkable {}
class OtherView extends View implements Checkable {}

private static <T extends View & Checkable> T get() {
return (T) checkableView;
}

OtherView otherView = Main.get();
CheckableView checkableView = Main.get();

但是您现在想对实现做什么?

 private <T extends View & Checkable> T get() {
return ...;
}

这个方法应该返回什么?如果您返回一个 CheckableView,编译器会说您必须将其转换为 T,因为客户端可能会将其转换为任何类型 T。但这也意味着您将收到 Unchecked cast from CheckableView to T 警告,因为如果客户端将其强制转换为 CheckableView 以外的任何其他类型,例如OhterView,你会得到一个ClassCastException

由于 get 方法实现者无法知道客户端会将其转换为哪种类型,因此他无法确定要返回哪个对象。

如果实现者返回特定对象(例如 CheckableView),则客户端只能将其转换为该类型。那么,为什么实现者不更改方法签名以准确返回该类型呢? ....或为这种情况引入特殊类型或接口(interface)?

也许这是适合您的解决方案

创建一个 get 方法将返回的接口(interface),例如

public interface CheckableView {
}

更改 get 方法以返回一个 CheckableView

private CheckableView get() {
}

编写一个适配器,将实现 CheckableView 适配为 CheckableView

public class CheckableViewAdapter<T extends View & Checkable> implements CheckableView {

private T checkableView;

public CheckableViewAdapter(T checkableView) {
this.checkableView = checkableView;
}
}

现在您可以为每个实现 CheckableView 创建 CheckableView 的实例

class SomeView extends View implements Checkable {}

SomeView someView = ...;
CheckableView checkableView = new CheckableViewAdapter<SomeView>(someView);

get方法的客户端需要的方法添加到CheckableView接口(interface)中,并在CheckableViewAdapter中实现。

public interface CheckableView {
public void bringToFront();
}

public class CheckableViewAdapter<T extends View & Checkable> implements CheckableView {

private T checkableView;

public CheckableViewAdapter(T checkableView) {
this.checkableView = checkableView;
}

public void bringToFront(){
checkableView.bringToFront();
}
}

或者只是

public interface CheckableView {
public View getView();
public Checkable getCheckable();
}

关于java - 如何正确返回从类扩展并实现接口(interface)的东西?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19677993/

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