简体   繁体   English

如何允许泛型类方法仅由某些类型的参数执行?

[英]How to allow a generic class method to be executed only by certain types of parameters?

I am trying to add a method to an existing class BinaryTree<T> to simple add the values of all the elements in the tree. 我正在尝试向现有类BinaryTree<T>添加方法,以简单地添加树中所有元素的值。 The problem is that being the class a generic one, not all the types that can be send at the time of creating a tree can be added. 问题在于,作为该类的泛型类,不能添加创建树时可以发送的所有类型。 I mean, for example It wouldn't make any sense to try to add the values of a class people . 我的意思是,例如,尝试添加class people的值没有任何意义。

So my question is, how do I make a method public T addAllElements() that only allows T to be an specific kind of type, in this case, only the types that is possible to add it's value, like Integer , Float , Long , etc? 因此,我的问题是,如何使方法public T addAllElements()仅允许T成为特定类型的类型的public T addAllElements() ,在这种情况下,仅允许可能添加其值的类型,例如IntegerFloatLong ,等等? I guess there have to be some kind of numerical interface or maybe some kind of declaration provided by the language to do something like that. 我想必须有某种数字接口或语言提供的某种声明才能执行类似的操作。

By the way, it seems to be a solution without having to create a child class, in case that it could help in anything, because I was asked to solve a similar problem and the instructions says that the method have to be in the same class. 顺便说一句,这似乎是一种解决方案,无需创建子类,以防万一它可以帮助任何事情,因为有人要求我解决类似的问题,并且说明说方法必须在同一类中。

Trying to be more clear, I'll ask another question , because I think that both of them have the same answer. 为了更加清晰,我将再问一个问题,因为我认为他们都有相同的答案。

I found that the method sort() in java.util.Arrays class can be used by a class if the class implements the interface Comparable<T> . 我发现,如果类实现接口Comparable<T>则该类可以使用java.util.Arrays类中的sort()方法。 So if I hava a class, lets say 所以如果我上课,可以说

public class People {
    implements Comparable<People>
    private String name;
    public int compareTo(People o) {
        ...
    }
    ...
}

This class can be sorted with the sort() method from the Arrays class, but if the class dind't implement the Comparable<T> interface it couldn't. 可以使用Arrays类中的sort()方法sort()此类进行排序,但是如果该类未实现Comparable<T>接口,则无法实现。 So what is making this restriction in the Arrays class definition? 那么,是什么在Arrays类定义中做出了这种限制? Is it what I need to solve the first problem I asked? 我需要解决第一个问题吗?

So my question is, how do I make a method public T addAllElements() that only allows T to be an specific kind of type, in this case, only the types that is possible to add it's value, like int , float , long , etc? 所以我的问题是,如何使一个方法T public T addAllElements()只允许T为一种特定类型的类型,在这种情况下,只允许可能添加其值的类型,例如intfloatlong ,等等? I guess there have to be some kind of numerical interface or maybe some kind of declaration provided by the language to do something like that. 我想必须有某种数字接口或语言提供的某种声明才能执行类似的操作。

You're looking for Number . 您正在寻找Number

So your declaration would look something like this, if the class is generic: 因此,如果该类是泛型的,则您的声明将类似于以下内容:

public BinaryTree<T extends Number> {
  // ...
}

or if you want to make just the method generic: 或者,如果您只想使方法通用:

public <T extends Number> T addAllElements() {
  // ...
}

That said, for better or for worse Number does not define arithmetic operations in terms of methods. 也就是说,无论好坏, Number都没有根据方法定义算术运算。 To my knowledge there is no such built-in type which does. 据我所知,没有这种内置类型可以。

Do note that the types you listed are all primitives, which mean they're not compatible with generics at all. 请注意,您列出的类型都是原语,这意味着它们根本与泛型不兼容。 Subtypes of Number (and types that can be used with generics) will all be wrapper types: Integer , Float , Long , etc. Number子类型(以及可以与泛型一起使用的类型)都将是包装器类型: IntegerFloatLong等等。

Your examples are related , but they're not the same. 您的示例是相关的 ,但它们并不相同。

To address the latter concern first, the reason that Arrays.sort with a specific signature requires that things be Comparable is because it needs to sort them based on that natural ordering. 为了首先解决后一个问题,具有特定签名的Arrays.sort要求事物是可Comparable是因为它需要根据该自然顺序对它们进行排序。 There is another signature that you could provide to the method which allows you to pass a custom Comparator to it, to sort on whatever other property of the class you liked. 您可以为该方法提供另一个签名,该签名允许您将自定义的Comparator传递给该方法,以对您喜欢的类的其他任何属性进行排序。

To your main concern, you need to have an upper-bound generic, specifically one of type T extends Number . 最主要的问题是,您需要具有上限泛型,特别是类型T extends Number The reason for this is that Number is the parent class to all of the numeric wrapper classes, as well as BigDecimal and BigInteger . 原因是Number是所有数字包装器类以及BigDecimalBigInteger的父类。

There's two things you'd want to be sure of before you did this: 在执行此操作之前,您需要确保两件事:

  • Your generic type was bound at the class level. 您的通用类型是在类级别绑定的。 Since we're dealing with a tree, it makes no sense to have non-homogeneous data throughout. 由于我们正在处理一棵树,因此在整个过程中拥有非均匀数据是没有意义的。
  • You did a math operation according to a specific data type ( int , long , or double ). 您根据特定的数据类型( intlongdouble )进行了数学运算。

You would then declare your method(s) as such: 然后,您将这样声明您的方法:

public int addAsInteger() {}
public double addAsDouble() {}
public long addAsLong() {}

You'd make use of Number 's methods : intValue , longValue and doubleValue for your respective methods. 您将为各自的方法使用Number的方法intValuelongValuedoubleValue

You wouldn't be able to simply return T since you can't guarantee what kind of Number you're getting back, or what T is specifically bound to (it can't be Number since it's an abstract class, so it is a non-inclusive upper bound). 你就不能简单地返回T ,因为你不能保证什么Number你要回来,或者什么T的特异性结合(它不能Number ,因为它是一个抽象类,所以它是一个非上限)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM