继承与泛型相媲美

时间:2015-11-12 09:39:30

标签: java generics comparable

尝试设计一个超类,确保所有子类本身都是Comparable

/**
 * A base class implementing Comparable with itself by delegation.
 * @param <T> - The type being wrapped.
 */
static class Distinct<T extends Comparable<T>> implements Comparable<Distinct<T>> {
    final T it;
    public Distinct(T it) {
        this.it = it;
    }
    @Override
    public int compareTo(Distinct<T> o) {
        return it.compareTo(o.it);
    }
}
/**
 * A set of distinct items.
 *
 * @param <T>
 */
static class ThingHolder<T extends Comparable<T>> {
    final Set<T> things;
    public ThingHolder() {
        this.things = new TreeSet<>();
    }
}
/**
 * A sample real thing.
 */
static class Thing extends Distinct<String> {
    public Thing(String it) {
        super(it);
    }
}
// This doesn't work - Why?
final ThingHolder<Thing> yz = new ThingHolder<>();

我得到的错误是:

com/oldcurmudgeon/test/Test.java:[70,22] error: type argument Thing is not within bounds of type-variable T
  where T is a type-variable:
    T extends Comparable<T> declared in class ThingHolder

为什么这不起作用?可以吗?

4 个答案:

答案 0 :(得分:2)

  1. 如果您将类型参数X传递给ThingHolder,则必须是Comparable<X>的子类型(通过ThingHolder的类声明)。
  2. 因此,如果您将类型Thing传递给ThingHolder,则必须是Comparable<Thing>的子类型。 (从Thing代替X来替代上一个陈述。)
  3. Thing扩展Distinct<String>,因此实现Comparable<Distinct<String>>(通过Thing的类声明。)
  4. ThingDistinct<String>的类型不同 - 虽然它是一个子类型 - 因此类型匹配失败。
  5. 您可以通过调整ThingHolder的类声明来解决此问题,如下所示:

    class ThingHolder<T extends Comparable<? super T>> {
        ...
    }
    

答案 1 :(得分:1)

一些研究和抨击提出了this suggestion

  

通常,如果您的API只使用类型参数T作为参数,则其使用应该利用较低的有界通配符(?super T)。

一些修改(添加? super T)稍微放宽限制条件:

/**
 * A set of distinct items.
 *
 * Don't like the <?> in there but a <T> is not accepted.
 *
 * @param <T>
 */
static class ThingHolder<T extends Comparable<? super T>> {

    final Set<T> things = new TreeSet<>();

}

final ThingHolder<Thing> holder = new ThingHolder<>();

这对编译器来说是可以接受的。

一般情况下,我不喜欢使用?来填补空白,因为它通常允许过多,但在这种情况下,我会将其留在那里。

答案 2 :(得分:0)

只需将<?php function GetDrivingDistance($lat1, $long1, $lat2, $long2) { $distance=""; $duration=""; $url = "https://maps.googleapis.com/maps/api/distancematrix /json?origins=".$lat1.",".$long1."&destinations=".$lat2.",".$long2."& mode=driving&language=pl-PL"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_PROXYPORT, 3128); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); $response = curl_exec($ch); curl_close($ch); $response_a = json_decode($response, true); // check the results if($response_a['status'] != 'OK' || $response_a['rows'][0]['elements'] [0]['status'] == "NOT_FOUND") { return false; } $dist = $response_a['rows'][0]['elements'][0]['distance']['text']; $time = $response_a['rows'][0]['elements'][0]['duration']['text'] return array('distance' => $dist, 'time' => $time); } $dist = GetDrivingDistance(17.5002541,78.4769027,17.4484114,78.3631118); if($dist) { echo 'Distance: '.$dist['distance'].' Travel time duration: '.$dist['time'].''; } else { echo "error"; } // php select option value from database $hostname = "localhost"; $username = "root"; $password = ""; $databaseName = "pbits"; // connect to mysql database $connect = mysqli_connect($hostname, $username, $password, $databaseName); // mysql select query $query = "SELECT standId, standName FROM `stands`"; // for method 1 $result1 = mysqli_query($connect, $query); $result2 = mysqli_query($connect, $query); ?> <html> <head> <title>dynamic dropdown </title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <table> <tr> <td> From Stand: </td> <td> to stand: </td> <td> Distance: </td> </tr> <tr> <td> <select> <?php while($row1 = mysqli_fetch_array($result1)):;?> <option value="<?php echo $row1[0];?>"><?php echo $row1[1];?></option> <?php endwhile;?> </select> </td> <td> <select> <?php while($row1 = mysqli_fetch_array($result2)):;?> <option value="<?php echo $row2[0];?>"><?php echo $row2[1];?></option> <?php endwhile;?> </select> </td> <td> <input type="text" name="distance" value=""> </td> </tr> </table> </body> </html> 班级签名更改为:

ThingHolder

即。从static class ThingHolder<T extends Comparable> { ... } 移除<T>,没有必要。

答案 3 :(得分:0)

class ThingHolder<T extends Comparable<T>>声明 thing T必须与自身相当,但class Thing extends Distinct<String>不是。