Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 调用方法时确定参数类型时出现问题_Scala_Generics - Fatal编程技术网

Scala 调用方法时确定参数类型时出现问题

Scala 调用方法时确定参数类型时出现问题,scala,generics,Scala,Generics,我很抱歉这个模糊或可能不正确的问题,但我甚至不知道如何用一句话来陈述我的问题 我有两个特点: trait Property[T] { val name: String def conformsTo(rule: Rule[T]): Boolean } 及 我有一个实现Property的具体类列表和一个规则实现的映射,其中两个参数化类型可以是Double或字符串。 当遍历此列表时,对于每个属性实例,我将一个具体的规则实现传递给符合方法,但是编译器会出现类型不匹配的错误 因此,从更广泛的意

我很抱歉这个模糊或可能不正确的问题,但我甚至不知道如何用一句话来陈述我的问题

我有两个特点:

trait Property[T] {
  val name: String

  def conformsTo(rule: Rule[T]): Boolean
}

我有一个实现
Property
的具体类列表和一个
规则
实现的映射,其中两个参数化类型可以是
Double
字符串
。 当遍历此列表时,对于每个
属性
实例,我将一个具体的
规则
实现传递给
符合
方法,但是编译器会出现类型不匹配的错误

因此,从更广泛的意义上讲,我试图获得的是一个属性列表,这些属性可以根据不同类型的给定规则集进行评估,而无需按类型将这些属性拆分为单独的列表

我尝试修补上/下限和隐式类型,但最终一无所获

完整代码:




trait Rule[T] {
  def evaluate(valueToCheck: T): Boolean
}

case class GreaterThan(value: Double) extends Rule[Double] {
  override def evaluate(valueToCheck: Double): Boolean = {
    valueToCheck > this.value
  }
}

case class LessThan(value: Double) extends Rule[Double] {
  override def evaluate(valueToCheck: Double): Boolean = {
    valueToCheck < this.value
  }
}

case class Is(value: String) extends Rule[String] {
  override def evaluate(valueToCheck: String): Boolean = {
    valueToCheck == this.value
  }
}

case class isNot(value: String) extends Rule[String] {
  override def evaluate(valueToCheck: String): Boolean = {
    valueToCheck != this.value
  }
}

trait Property[T] {
  val name: String

  def conformsTo(rule: Rule[T]): Boolean
}

case class DoubleProperty(name: String, value: Double) extends Property[Double] {
  override def conformsTo(rule: Rule[Double]): Boolean = rule.evaluate(value)
}

case class StringProperty(name: String, value: String) extends Property[String] {
  override def conformsTo(rule: Rule[String]): Boolean = rule.evaluate(value)
}

object Evaluator extends App {

  val ruleMap = Map(
    "name1" -> GreaterThan(123),
    "name1" -> LessThan(500),
    "name2" -> GreaterThan(1000),
    "name3" -> Is("something"))
  val numericProperty = DoubleProperty("name1", 600)
  val numericProperty2 = DoubleProperty("name2", 1000)
  val stringProperty = StringProperty("name3", "something")
  val stringProperty2 = StringProperty("name4", "something")

  val attributes = List(
    numericProperty,
    numericProperty2,
    stringProperty,
    stringProperty2)

  val nonConforming = attributes
    .filter(x => ruleMap.contains(x.name))
    .filter(x => !x.conformsTo(ruleMap(x.name))).toList

}


特质规则[T]{
def evaluate(valueToCheck:T):布尔值
}
案例类大于(值:Double)扩展了规则[Double]{
覆盖def求值(valueToCheck:Double):布尔={
valueToCheck>this.value
}
}
case类LessThan(值:Double)扩展了规则[Double]{
覆盖def求值(valueToCheck:Double):布尔={
valueToCheck大于(123),
“名称1”->小于(500),
“名称2”->大于(1000),
“name3”->是(“某物”))
val numericProperty=DoubleProperty(“名称1”,600)
val numericProperty2=双重属性(“名称2”,1000)
val stringProperty=stringProperty(“name3”,“某物”)
val stringProperty2=StringProperty(“名称4”,“某物”)
val属性=列表(
数字属性,
数字属性2,
stringProperty,
stringProperty2)
val=属性
.filter(x=>ruleMap.contains(x.name))
.filter(x=>!x.conformsTo(ruleMap(x.name))).toList
}
错误:

type mismatch;
 found   : Product with Rule[_ >: String with Double] with java.io.Serializable
 required: Rule[(some other)<root>._1]
Note: Any >: _1 (and Product with Rule[_ >: String with Double] with java.io.Serializable <: Rule[_ >: String with Double]), but trait Rule is invariant in type T.
You may wish to define T as -T instead. (SLS 4.5)
    .filter(x => !x.conformsTo(ruleMap(x.name))).toList
类型不匹配;
找到:具有规则[\u>:String with Double]且java.io.Serializable的产品
必需:规则[(某些其他)。\u 1]
注意:Any>:_1(以及java.io.Serializable:String with Double)中带有规则[>:String with Double]的产品),但trait规则在类型T中是不变的。
您可能希望将T定义为-T。(补充说明4.5)
.filter(x=>!x.conformsTo(ruleMap(x.name))).toList

感谢您的帮助。

首先,根据错误消息,可以从可序列化的
产品中扩展
规则

然后,错误消息更改为:

类型不匹配;
找到:App.Rule[_1(值$anonfun)],其中类型_1(值$anonfun)>:带双精度的字符串
必需:应用规则[._1]
其次,您可以使
规则
逆变

trait Rule[-T] extends Product with Serializable {
  def evaluate(valueToCheck: T): Boolean
}
类型不匹配;
找到:App.Rule[带双精度的字符串]
必需:应用规则[_1]
属性
协变

trait Property[+T] {
  val name: String
  def conformsTo(rule: Rule[T]): Boolean
}
类型不匹配;
找到:App.Rule[带双精度的字符串]
必需:应用程序规则[任何]
问题是这不适用于
列表
attributes
的元素具有类型
Property[Double]
Property[String]
。但当您将它们添加到列表中时,它们丢失了各自的类型,变成了
Property[Any]
Property[Double | String]
,如果Scala 2中有联合类型)

类似地,
ruleMap
的值具有类型
Rule[Double]
Rule[String]
。但是当你把它们和一些键放进地图时,它们丢失了各自的类型,变成了
Rule[Double with String]
(甚至
Rule[Nothing]

如果没有修改
属性
规则
的差异,则类型将是
属性[\u]
规则[\u]
(实际上,
属性[\u1]
规则[\u2]
),其中类型参数彼此不对应

但是
conformsTo
的签名表示
property.conformsTo(rule)
仅当参数具有相同
T
的类型
property[T]
rule[T]
时才编译,这是无法保证的


您可以尝试使用而不是
列表
和而不是
映射
,以保留单个类型的元素。但是为了使
过滤器
工作,您应该知道
ruleMap.contains(x.name)
在编译时是否包含。因此,您必须使键具有单例类型和trait
Property
才能依赖于这一个类型参数
trait Property[+T,S我相信简单的解决方案是为属性和规则的可能类型创建一个简单的ADT。@LuisMiguelMejíaSuárez如果我们执行
筛选{case x:Property[T]=>x.conformsTo(ruleMap(x.name).asInstanceOf[Rule[t]]))
?我真的不太了解类型模式,我相信它是有效的,但在我看来它是不安全的。谢谢你的回答。@LuisMiguelMejíaSuárez-你能详细说明,你是指代数数据类型吗?@DmytroMitin是的,正如我所说,你的选择可能是安全的,而且显然更短。但老实说,我会做你所做的在那辆马车里
trait Property[+T] {
  val name: String
  def conformsTo(rule: Rule[T]): Boolean
}
val nonConforming = attributes
  .filter(x => ruleMap.contains(x.name))
  .filter{
    case x: Property[t] => !x.conformsTo(ruleMap(x.name).asInstanceOf[Rule[t]])
  }