如何引用 Java 中接口实现的类类型?

发布于 2024-12-16 13:47:14 字数 697 浏览 2 评论 0原文

我在编写的程序中遇到了接口问题。我想创建一个接口,其方法之一接收/返回对自己对象类型的引用。就像这样:

public interface I {
    ? getSelf();
}

public class A implements I {
    A getSelf() {
        return this;
    }
}

public class B implements I {
    B getSelf() {
        return this;
    }
}

我不能在“?”处使用“I”,因为我不想返回对接口的引用,而是返回对类的引用。我搜索了一下,发现Java中没有办法“自引用”,所以我不能直接用“?”来代替。在“self”关键字或类似内容的示例中。实际上,我想出了一个类似的解决方案

public interface I<SELF> {
    SELF getSelf();
}

public class A implements I<A> {
    A getSelf() {
        return this;
    }
}

public class B implements I<B> {
    B getSelf() {
        return this;
    }
}

,但这看起来确实是一种解决方法或类似的方法。还有其他方法吗?

I came to a problem with interfaces in a program I'm making. I want to create a interface which have one of its methods receiving/returning a reference to the type of the own object. It was something like:

public interface I {
    ? getSelf();
}

public class A implements I {
    A getSelf() {
        return this;
    }
}

public class B implements I {
    B getSelf() {
        return this;
    }
}

I can't use an "I" where it's a "?", because I don't want to return a reference to the interface, but the class. I searched and found that there are no way to "self-refer" in Java, so I can't just substitute that "?" in the example for a "self" keyword or something like this. Actually, I came up to a solution that goes like

public interface I<SELF> {
    SELF getSelf();
}

public class A implements I<A> {
    A getSelf() {
        return this;
    }
}

public class B implements I<B> {
    B getSelf() {
        return this;
    }
}

But it really seems like a workaround or something alike. Is there another way to do so?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

意中人 2024-12-23 13:47:14

有一种方法可以在扩展接口时强制使用自己的类作为参数:

interface I<SELF extends I<SELF>> {
    SELF getSelf();
}

class A implements I<A> {
    A getSelf() {
        return this;
    }
}

class B implements I<A> { // illegal: Bound mismatch
    A getSelf() {
        return this;
    }
}

这甚至在编写泛型类时也有效。唯一的缺点:必须将 this 转换为 SELF

正如 Andrey Makarov 在

class A<SELF extends A<SELF>> {
    SELF getSelf() {
        return (SELF)this;
    }
}
class C extends A<B> {} // Does not fail.

// C myC = new C();
// B myB = myC.getSelf(); // <-- ClassCastException

There is a way to enforce using ones own class as a parameter when extending an interface:

interface I<SELF extends I<SELF>> {
    SELF getSelf();
}

class A implements I<A> {
    A getSelf() {
        return this;
    }
}

class B implements I<A> { // illegal: Bound mismatch
    A getSelf() {
        return this;
    }
}

This even works when writing generic classes. Only drawback: one has to cast this to SELF.

As Andrey Makarov noted in a comment below this does not work reliably when writing generic classes.

class A<SELF extends A<SELF>> {
    SELF getSelf() {
        return (SELF)this;
    }
}
class C extends A<B> {} // Does not fail.

// C myC = new C();
// B myB = myC.getSelf(); // <-- ClassCastException
终止放荡 2024-12-23 13:47:14

Java 支持协变返回类型,因此这是一种选择。利用 AB 均派生自 Object 的事实:

public interface I {
    Object getSelf();  // or I, see below
}
public class A implements I {
    A getSelf() { return this; }
}
public class B implements I {
    B getSelf() { return this; }
}

要点是 A.getSelf()< /code> 和 B.getSelf()I.getSelf() 的合法重写,即使它们的返回类型不同。这是因为每个 A 都可以被视为 Object,因此返回类型与该对象的返回类型兼容基函数。 (这称为“协方差”。)

事实上,由于 AB 也已知源自 I,因此您可以替换 出于同样的原因,I 拒绝了

协方差通常是一件好事:拥有 I 类型的接口对象的人可以调用 getSelf() 并获取另一个接口,这就是她需要知道的全部内容。另一方面,已经知道自己有一个 A 对象的人可以调用 getSelf() 并且实际上会获取另一个 A 对象。附加信息可用于获取更具体的派生类型,但缺乏该信息的人仍然可以获得接口基类规定的所有内容:

I x = new A();
A y = new A();

I a = x.foo();    // generic
A b = y.foo();    // we have more information, but b also "is-an" I
A c = (A)x.foo(); // "cheating" (we know the actual type)

Java supports covariant return types, so that's one option. Take advantage of the fact that both A and B are derived from Object:

public interface I {
    Object getSelf();  // or I, see below
}
public class A implements I {
    A getSelf() { return this; }
}
public class B implements I {
    B getSelf() { return this; }
}

The point is that both A.getSelf() and B.getSelf() are legitimate overrides of I.getSelf(), even though their return type is different. That's because every A can be treated like an Object, and so the return type is compatible with that of the base function. (This is called "covariance".)

In fact, since A and B are also known to derive from I, you can replace Object by I for the same reasons.

Covariance is generally a Good Thing: Someone who has an interface object of type I can call getSelf() and get another interface, and that's all she needs to know. On the other hand, someone who already knows he has an A object can call getSelf() and will actually get another A object back. The additional information can be used to get a more specific derived type, but someone who lacks that information still gets everything that's prescribed by the interface base class:

I x = new A();
A y = new A();

I a = x.foo();    // generic
A b = y.foo();    // we have more information, but b also "is-an" I
A c = (A)x.foo(); // "cheating" (we know the actual type)
め七分饶幸 2024-12-23 13:47:14

我想知道是否还有其他方法可以做到这一点?

可以如下编写:

public interface I {
   I getSelf();
}

然后将结果转换为您想要的类型。您现有的 AB 类将按原样工作。

(这是返回类型协变的一个示例。Java 5 中添加了对返回类型协变的支持。这种方法会在较旧的 JDK 中给出编译错误。)

替代版本(您称其为解决方法,但实际上并不是这样) )使用泛型可以避免显式类型转换。然而,生成的代码和运行时存在隐式类型转换……除非 JIT 编译器可以将其优化掉。

AFAIK,没有更好的选择。

I was wondering if there are any other way to do so?

You can write it as follows:

public interface I {
   I getSelf();
}

and then cast the result to the type you want. Your existing A and B classes will work as-is.

(This is an example of return type covariance. Support for return type covariance was added in Java 5. This approach will give compilation errors in older JDKs.)

The alternative version (you call it a work-around, but it isn't really) that uses generics allows you to avoid the explicit typecast. However, there is an implicit typecast in the generated code, and at runtime ... unless the JIT compiler can optimize it away.

There are no better alternatives, AFAIK.

亽野灬性zι浪 2024-12-23 13:47:14

正如其他人所说,您可以覆盖实现类中的返回类型:

public interface I {
    public I getSelf();
}

public class A implements I {
    @Override
    public A getSelf() {
        return this;
    }
}

但是,我有两个“为什么”问题要问您:

1:为什么您希望接口返回实现对象?对我来说,这似乎违背了接口和继承的一般思想。您能举例说明如何使用它吗?

2:无论如何,你为什么想要这个功能?如果a.getSelf() == a,为什么不直接使用a呢?

As others have said, you can override the return type in the implementing classes:

public interface I {
    public I getSelf();
}

public class A implements I {
    @Override
    public A getSelf() {
        return this;
    }
}

However, I have two 'why' questions for you:

1: Why do you want an Interface to return the implementing object? It seems to run against the general ideas of interfaces and inheritance to me. Can you show an example of how this might be used?

2: In any case, why would you want this function? If a.getSelf() == a, why not just use a?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文