【问题标题】:Scala variance when multiple types多种类型时的Scala差异
【发布时间】:2019-03-17 20:34:03
【问题描述】:

通过这个答案https://stackoverflow.com/a/1759565/11217621,我知道在 Java 中可以做类似的事情

public class MyClass<S, T> {
   public        void foo(Set<S> s, Set<T> t); //same type params as on class
   public <U, V> void bar(Set<U> s, Set<V> t); //type params independent of class
}

其中bar 方法的&lt;U, V&gt; 独立于类参数类型。

我有一个简单的 Java 数据类,比如

public class DataPoint<T> {

    public long timeStampMs;
    public T value;

    public <R> DataPoint<R> withNewValue(R newValue){
        return new DataPoint(this.timeStampMs, newValue);
    }

    public KeyedDataPoint withKey(String key){
        return new KeyedDataPoint(key, this.timeStampMs, this.value);
    }
}

...以这样的方式,从原始的DataPoint&lt;Long&gt;,我将一些映射函数应用于value 字段,并且值变成了 Double。通过使用withNewValue方法实例化new DataPoint&lt;Double&gt;是没有问题的

public DataPoint<Double> map(DataPoint<Long> dataPoint) {
    double phase = (double) currentStep / numSteps;
    return dataPoint.withNewValue(phase);
}

我需要将它迁移到 Scala,但我不知道该怎么做。我正在尝试做类似的事情:

class DataPoint[T1] (val timeStampMs: Long, val value: T1) {
    def withNewValue(value: T2): DataPoint[T2] = new DataPoint[T2](this.timeStampMs, value)
    def withKey(key: String): KeyedDataPoint[T1] = new KeyedDataPoint(key, this.timeStampMs, this.value)
}

...无法编译。还尝试了有关 Scala 协变和逆变的官方文档的几种组合,但我仍处于使用 Scala 的第一步。

【问题讨论】:

  • 如果您将第一个方法声明为withNewValue[T2] 并添加KeyedDataPoint 的定义,那么您的示例似乎编译得很好,没有任何方差注释。不确定实际问题是什么。
  • 谢谢安德烈,成功了!

标签: scala generics apache-flink


【解决方案1】:

您只是缺少withNewValue 上的类型参数[T2]

class DataPoint[T1] (val timeStampMs: Long, val value: T1) {
    def withNewValue[T2](value: T2): DataPoint[T2] = new DataPoint[T2](this.timeStampMs, value)
    def withKey(key: String): KeyedDataPoint[T1] = new KeyedDataPoint(key, this.timeStampMs, this.value)
}

Compiles just fine.

【讨论】:

  • 谢谢 Markus,我在 Internet 上的任何地方都找不到怎么做 :) 顺便说一句,你知道是否有任何具体的术语来指代这个,我找不到任何东西只查找“类型差异”或“泛型”
  • @diegoruizbarbero“类型参数”?如果类型参数列表不存在,则类型参数T2不可用。
  • @diegoruizbarbero 是的,“类型参数”是您正在寻找的术语。 Java 中的 &lt;T&gt; 是 Scala 中的 [T] - 语法略有不同。
  • 我得到了[T] 的语法,就像&lt;T&gt; 一样……但让我感到困惑的是:public &lt;R&gt; DataPoint&lt;R&gt; withNewValue(R newValue)。如果DataPoint&lt;R&gt; 是函数的新(第二个)返回类型,那么&lt;R&gt; DataPoint&lt;R&gt; 中的第一个&lt;R&gt; 是什么?有这个词吗?
  • @diegoruizbarbero 澄清一下,这两个是完全分离的,并且只有一种返回类型:DataPoint&lt;R&gt;&lt;R&gt; 声明该函数包含一个参数类型(在这种情况下在返回类型中使用)。这就是 imo Scala 的语法更有意义的原因,因为类型参数的定义类似于普通参数,而不是像 Java 中的“方法前面的某个位置”。想想:def myFunc[... type parameters...](... value parameters...)
猜你喜欢
  • 2014-06-16
  • 2018-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-15
  • 2013-12-01
  • 1970-01-01
相关资源
最近更新 更多