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_Types_Projection - Fatal编程技术网

Scala 如何在方法参数中使用泛型类型投影?

Scala 如何在方法参数中使用泛型类型投影?,scala,generics,types,projection,Scala,Generics,Types,Projection,我有案例类,对于每个案例类T,我定义一个实体[T]隐式。这些实例定义了一个特定于每个T的Id类型。然后,我使用一个检索方法定义了一个抽象表[T]类,该方法通过类型投影获取T中定义的Id类型的标识符 但它不起作用,我得到类型不匹配: scalac generic-type-projection.scala generic-type-projection.scala:31: error: type mismatch; found : id.type (with underlying type

我有案例类,对于每个案例类T,我定义一个实体[T]隐式。这些实例定义了一个特定于每个T的Id类型。然后,我使用一个检索方法定义了一个抽象表[T]类,该方法通过类型投影获取T中定义的Id类型的标识符

但它不起作用,我得到类型不匹配:

scalac generic-type-projection.scala
generic-type-projection.scala:31: error: type mismatch;
 found   : id.type (with underlying type Entity[T]#Id)
 required: _5.Id where val _5: Entity[T]
        val key = implicitly[Entity[T]].keyFromId(id)  // Type mismatch on 'id'.
                                              ^
generic-type-projection.scala:41: error: type mismatch;
 found   : String("dummy")
 required: Entity[A]#Id
    t.retrieve("dummy")
           ^
two errors found
代码如下:

import java.util.UUID
特质实体[T]{
类型Id
类型键
def getId(实体:T):Id
def keyFromId(id:id):密钥
}
案例类别A(f1:String,f2:Int)
对象对象对象{
隐式对象实体扩展实体[A]{
类型Id=字符串
类型Key=UUID
def getId(实体:A)=实体.f1
def keyFromId(id:String)=UUID.fromString(id)
}
}
对象主体{
抽象类表[T:实体]{
def存储(实体:T):单位
def检索(id:Entity[T]#id):选项[T]
}
def makeTable[T:实体]:表[T]=
新表格[T]{
def存储(实体:T):单位={}
def检索(id:实体[T]#id):选项[T]={
val key=隐式地[Entity[T]]。keyFromId(id)//id上的类型不匹配。
没有一个
}
}
def main(参数:数组[字符串]){
导入AImplicits_
val t=可生成表[A]
val a=a(“虚拟”,9)
t、 商店(a)
t、 检索(“dummy”)//在“dummy”上的类型不匹配。
}
}

非常感谢您的帮助。

当您扩展上下文绑定速记时,类型不匹配更容易看到。请记住,
[T:Entity]
语法只是要求隐式
实体[T]
在范围内的语法糖。因此,
makeTable
函数的标题实际上是:

def makeTable[T](implicit entity: Entity[T]): Table[T] =
现在有了作用域中的隐式参数,函数中的
隐式
调用将获取该值(实际上,
新表[T]
构造函数获取隐式,然后
隐式
从那里获取它),因此
makeTable
函数以其扩展形式:

def makeTable[T](implicit entity: Entity[T]): Table[T] =
  new Table[T] {
    def store(entity: T): Unit = {}
    def retrieve(id: Entity[T]#Id): Option[T] = {
      val key = entity.keyFromId(id)  // Type mismatch on 'id'.
      None
    }
  }
请注意,
retrieve
id
参数的类型声明没有进行转换。本质上,编译器抱怨
entity.keyFromId
需要类型为
entity.Id
的参数,但是
Id
参数是抽象类型
entity[T]#Id


这里的问题是,您想对
类的用户隐藏
实体
和Id,但您想在其中一个方法中公开
Id的类型。假设我有两个
表[T]
的实例,但它们使用不同的
实体[T]
实现——它们的
Id
类型实际上是不同的。表实例的用户如何知道传递给
retrieve
函数的类型?您可以通过向
类添加另一个类型参数来解决此问题。您仍然可以抽象出id/密钥生成逻辑,但这将允许编译器进行类型检查,以确保
retrieve
函数获得正确类型的参数。

def store(entity:E):Unit
E
是什么。应该没有Es,只有Ts。我编辑了代码。谢谢。你说得对,这是一个路径依赖型问题。我的问题表述得很糟糕,因为我实际上在寻找一种解决方案,使隐式参数的类型与抽象类型匹配(在类型投影中)。。。我最终找到了一种方法,使用一个早期的初始值设定项,将抽象val设置为隐式对象。接受你的回答。