这个通用类声明可能意味着什么?

发布于 2024-12-06 04:32:01 字数 329 浏览 0 评论 0 原文

我知道这不是一个好问题,我可能会被诅咒问这个问题,但我找不到任何地方可以获得这个问题的帮助,

下面是我的面试问题中出现的通用类(我已经失败了)。问题是要告诉这个类声明正在做什么以及在什么情况下可以使用它?

我对泛型编程的理解非常有限,但我知道“T”是类型,“扩展”在这里意味着类型应该继承“SimpleGenericClass”,但我不理解“?”最后以及在什么情况下可以使用该类

public abstract class SimpleGenericClass<T extends SimpleGenericClass<?>> {

}

I know this isn't a good question to ask and I might get cursed to ask it but I cannot find any place to get help on this question

Below is a Generic class that appeared in my interview question (which I have already failed). The question was to tell what this Class declaration is doing and in what circumstances this could be used for ?

I have very limited understanding of Generic programming but I understand that 'T' is Type and 'extends' here means that the Type should have inherited 'SimpleGenericClass' but I do not understand the '?' at the end and in what circumstances this Class could be potentially used for

public abstract class SimpleGenericClass<T extends SimpleGenericClass<?>> {

}

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

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

发布评论

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

评论(5

傲世九天 2024-12-13 04:32:01

首先,因为 SimpleGenericClass 类是抽象,所以它应该被子类化。

其次,它是一个通用类,这意味着在类内部的某个地方,您几乎肯定会使用通用参数T作为字段的类型。

public abstract class SimpleGenericClass<T...> {
    T x;
}

现在,第一个有趣的事情是 T有界的。因为它被声明为 T extends SimpleGenericClass,所以它只能是 SimpleGenericClassSimpleGenericClass> 的某个子类>。您还询问了。这就是所谓的通配符,在 Java 通配符教程。在你的情况下,我们会说这是一个“未知的 SimpleGenericClass”。在 Java 中需要它,因为 SimpleGenericClass不是 SimpleGenericClass 的超类。

第二有趣的事情是,由于T是某种SimpleGenericClass,您的类很可能定义递归结构< /em>.我想到的是树(想想表达式树),其中 SimpleGenericClass 是(抽象)节点类型,旨在用各种专用节点类型进行子类化。

更新 这个关于自界泛型的问题可能是对你有帮助。

更新2

我继续编写了一些代码来说明如何使用它。该应用程序不执行任何操作,但它会进行编译,并向您展示通用边界如何提供一些可能有意义的约束。

public abstract class Node<T extends Node<?>> {
    public abstract T[] getChildren();
}

class NumberNode extends Node {
    int data;
    public Node[] getChildren() {return new Node[]{};}
}

class IdentifierNode extends Node {
    int data;
    public Node[] getChildren() {return new Node[]{};}
}

class PlusNode extends Node {
    NumberNode left;
    NumberNode right;
    public NumberNode[] getChildren() {return new NumberNode[]{};}
}

这里的好处是 NumberNode[]PlusNode.getChildren 的有效返回类型!这在实践中重要吗?不知道,但这很酷。 :)

这不是最好的例子,但问题相当开放(“这样的东西可以用来做什么?”)。当然,还有其他方法来定义树。

First, because the class SimpleGenericClass is abstract, it is meant to be subclassed.

Second, it is a generic class which means that inside the class somewhere you will almost assuredly be using the generic parameter T as the type of a field.

public abstract class SimpleGenericClass<T...> {
    T x;
}

Now the first interesting thing here is that T is bounded. Because it is declared as T extends SimpleGenericClass<?> it can only be SimpleGenericClass<?> or some subclass of SimpleGenericClass<?>. You also asked about thr ?. That's known as a wildcard and there is a pretty good explanation of it at the Java Tutorial on Wildcards. In your case we would say this is a "SimpleGenericClass of unknown." It is needed in Java because SimpleGenericClass<Object> is NOT the superclass of SimpleGenericClass<String>, for example.

The second interesting thing though is that since T is a SimpleGenericClass of some sort, your class is more than likely defining recursive structures. What comes to my mind are trees (think of expression trees) where SimpleGenericClass is the (abstract) node type, designed to be subclassed with all kinds of specialized node types.

UPDATE This SO question on self-bounded generics might be helpful to you.

UPDATE 2

I went ahead and put together some code that illustrates how this can be used. The app doesn't do anything but it does compile and it shows you how the generic bounds can supply some possibly-meaningful constraints.

public abstract class Node<T extends Node<?>> {
    public abstract T[] getChildren();
}

class NumberNode extends Node {
    int data;
    public Node[] getChildren() {return new Node[]{};}
}

class IdentifierNode extends Node {
    int data;
    public Node[] getChildren() {return new Node[]{};}
}

class PlusNode extends Node {
    NumberNode left;
    NumberNode right;
    public NumberNode[] getChildren() {return new NumberNode[]{};}
}

The nice thing here is that NumberNode[] is a valid return type for PlusNode.getChildren! Does that matter in practice? No idea, but it is pretty cool. :)

It's not the greatest example, but the question was rather open ended ("what might such a thing be used for?"). There are other ways to define trees, of course.

回眸一笑 2024-12-13 04:32:01

这实际上仅意味着您允许 SimpleGenericClass 类的用户使用类型 T 来参数化该类的实例。但是,T 不能是任何类型,而必须是 SampleGenericClass(或 SampleGenericClass 本身)的子类型。

在类 SimpleGenericClass 的其余代码中,您可以在方法签名中使用类型 T。

让我们假设 SimpleGenericClass 不是抽象的。使用它时,您可以这样写:

new SimpleGenericClass<SampleGenericClass<String>>();

即您用 SampleGenericClass 参数化 SimpleGenericClass,用 String 参数化 SampleGenericClass。

This really only means that you allow the user of class SimpleGenericClass to parametrize instances of the class with the type T. However, T cannot be any type, but must be a subtype of SampleGenericClass (or SampleGenericClass itself).

In the remainder of the code of class SimpleGenericClass you may use type T in method signatures.

Let's assume for a second that SimpleGenericClass is not abstract. When using it, you could then write:

new SimpleGenericClass<SampleGenericClass<String>>();

I.e. you parametrize SimpleGenericClass with SampleGenericClass and SampleGenericClass with String.

马蹄踏│碎落叶 2024-12-13 04:32:01

这基本上是说:在这个类中,您有一个名为 T 的类型占位符,并且对该占位符的限制是,它必须是 SimpleGenericClass 类型或扩展它的类型。一旦遵守该规则,您就可以创建类的实例并向 T 提供实际类型,稍后可以在该类的方法中使用该类型,如下所示:

public class C <T extends Number>{

    public void doSomething(T t) {

    }

    public static void main(String... args) {
        //works:
        C<Number> c = new C<Number>();
        c.doSomething(new Number() {
            //Aonimous implementation of number

        });

        //won't work
        //C<Object> c = new C<Object>();

        C<Integer> c2 = new C<Integer>();       
        c2.doSomething(new Integer(1));
        //won't work
        //c2.doSomething(new Number() {

            //Aonimous implementation of number
        //});
    }
}

SimpleGenericClass 是在这一点上相当多余。如果此类需要另一种泛型类型,则可以有多个泛型类型 (SimpleGenericClass)

This basically sais: in this class you have a Type placeholder called T, and a restriction on that placeholder, it must be of type SimpleGenericClass or something that extends it. Once you obey that rule you can create instances of your class and give an actual type to T, that later on can be used in methods of that class, something like this:

public class C <T extends Number>{

    public void doSomething(T t) {

    }

    public static void main(String... args) {
        //works:
        C<Number> c = new C<Number>();
        c.doSomething(new Number() {
            //Aonimous implementation of number

        });

        //won't work
        //C<Object> c = new C<Object>();

        C<Integer> c2 = new C<Integer>();       
        c2.doSomething(new Integer(1));
        //won't work
        //c2.doSomething(new Number() {

            //Aonimous implementation of number
        //});
    }
}

The SimpleGenericClass<?> is pretty redundant at this point. If another generic type is needed on this class, you can have more than one (SimpleGenericClass<T extends SimpleGenericClass, T2 extends Whatever>)

攒眉千度 2024-12-13 04:32:01

根据定义,它表示 SimpleGenericClass 可以在 类型上工作,该类型是 SimpleGenericClass 的子类。

所以我假设会有一些操作适用于

现在看看为什么人们会定义这样的模板 - (我真的想不到太多)可能是这样一种情况,其中 SimpleGenericClass 是一个抽象类(刚刚意识到它是按照OP:P)并期望它可以在任何具体类上工作?

伙计们你觉得怎么样?

By definition it says that the SimpleGenericClass can work on a type <T> which is subclass of SimpleGenericClass.

So I assume there will be some operations which will work on <T>.

Now to see why one would define a template like this - (not much I can think of , really ) may be a scenario where the SimpleGenericClass is an abstract class (just realized it is as per OP :P) and expects that it can work on any concrete classes ?

Guys what do you think ?

独闯女儿国 2024-12-13 04:32:01

我想您已经得到了这种形式的问题(T 而不是 ):

public abstract class SimpleGenericClass<T extends SimpleGenericClass<T>>

看一下这段代码:

abstract class Foo<SubClassOfFoo extends Foo<SubClassOfFoo>>
{
    /** subclasses are forced to return themselves from this method */
    public abstract SubClassOfFoo subclassAwareDeepCopy();
}

class Bar extends Foo<Bar> {
    public Bar subclassAwareDeepCopy() {
        Bar b = new Bar();
        // ...
        return b;
    }
}

Bar b = new Bar();
Foo<Bar> f = b;
Bar b2 = b.subclassAwareDeepCopy();
Bar b3 = f.subclassAwareDeepCopy(); // no need to cast, return type is Bar

Foo> 是:

  • Foo 的任何子类都必须向 Foo 提供类型参数。
  • 该类型参数实际上必须是 Foo 的子类。
  • Foo 的子类(如 Bar)遵循以下习惯用法:类型
    它们提供给 Foo 的参数是它们自己。

  • Foo 有一个返回 SubClassOfFoo 的方法。组合
    通过上面的习惯用法,这使得 Foo 可以制定一个合约:
    说“我的任何子类都必须实现 subclassAwareDeepCopy() 并且
    他们必须声明它返回实际的子类“。

换句话说:这个习惯用法允许超类(例如抽象工厂)定义其参数类型和返回类型是子类类型而不是超类类型的方法。

例如,该技巧在 Enum JDK 类中完成:

public abstract class Enum<E extends Enum<E>>

请参阅此处了解更多详情。

I guess you have got the question in this form (T instead of ?):

public abstract class SimpleGenericClass<T extends SimpleGenericClass<T>>

Take a look at this code:

abstract class Foo<SubClassOfFoo extends Foo<SubClassOfFoo>>
{
    /** subclasses are forced to return themselves from this method */
    public abstract SubClassOfFoo subclassAwareDeepCopy();
}

class Bar extends Foo<Bar> {
    public Bar subclassAwareDeepCopy() {
        Bar b = new Bar();
        // ...
        return b;
    }
}

Bar b = new Bar();
Foo<Bar> f = b;
Bar b2 = b.subclassAwareDeepCopy();
Bar b3 = f.subclassAwareDeepCopy(); // no need to cast, return type is Bar

The trick going on with Foo<SubClassOfFoo extends Foo<SubClassOfFoo>> is:

  • Any subclass of Foo must supply a type argument to Foo.
  • That type argument must actually be a subclass of Foo.
  • Subclasses of Foo (like Bar) follow the idiom that the type
    argument they supply to Foo is themselves.

  • Foo has a method that returns SubClassOfFoo. Combined
    with the above idiom, this allows Foo to formulate a contract that
    says “any subclass of me must implement subclassAwareDeepCopy() and
    they must declare that it returns that actual subclass“.

To say that another way: this idiom allows a superclass (such as an Abstract Factory) to define methods whose argument types and return types are in terms of the subclass type, not the superclass type.

The trick is done for example in Enum JDK class:

public abstract class Enum<E extends Enum<E>>

Refer here for more details.

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