我有一个通用案例类Route,它接受Location的子类列表。但是,在以下方法中,我在调用server {
listen 80;
server_name "";
root /var/www/html/site/web;
location / {
try_files $uri /app.php$is_args$args;
}
location ~ ^.*/(app_dev|config)\.php(/|$) {
fastcgi_pass lockate_site:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $document_root;
}
}
distance
expected: head.T, actual: T
基本的抽象位置类如下
case class Route[T <: Location](route: List[T]) {
def measureDistance: Double = {
def measure(head: T, tail: List[T], acc: Double = 0.0): Double = tail match {
case Nil => acc
case h :: t => measure(h, t, head.distance(h) + acc)
}
if (route.isEmpty) 0.0
else measure(route.head, route.tail)
}
}
由于head和h都来自同一个列表abstract class Location(val name: String) {
type T <: Location
def distance(that: T): Double
}
,我无法理解为什么这些类型不同。
答案 0 :(得分:3)
在这种情况下看起来好像是F-bounded多态:
abstract class Location[L <: Location[L]](val name: String) {
def distance(that: L): Double
}
case class Route[T <: Location[T]](route: List[T]) {
def measureDistance: Double = {
def measure(head: T, tail: List[T], acc: Double = 0.0): Double = tail match {
case Nil => acc
case h :: t => measure(h, t, head.distance(h) + acc)
}
if (route.isEmpty) 0.0
else measure(route.head, route.tail)
}
}
但是,您也可以考虑使用Metric
- 类型代码:
trait Metric[L] {
def dist(a: L, b: L): Double
}
case class Route[T: Metric](route: List[T]) {
def measureDistance: Double = {
def measure(head: T, tail: List[T], acc: Double = 0.0): Double = tail match {
case Nil => acc
case h :: t => measure(h, t, implicitly[Metric[T]].dist(head, h) + acc)
}
if (route.isEmpty) 0.0
else measure(route.head, route.tail)
}
}
后一种解决方案适用于更多类型,例如适用于(Double, Double)
,即使它们不是从Location
继承。
这是类型类解决方案,但是使用稍微更优雅的Cats风格语法可以避免implicitly
:
trait Metric[L] {
def dist(a: L, b: L): Double
}
object Metric {
def apply[T](implicit m: Metric[T]): Metric[T] = m
}
case class Route[T: Metric](route: List[T]) {
def measureDistance: Double = {
def measure(head: T, tail: List[T], acc: Double = 0.0): Double = tail match {
case Nil => acc
case h :: t => measure(h, t, Metric[T].dist(head, h) + acc)
}
if (route.isEmpty) 0.0
else measure(route.head, route.tail)
}
}
答案 1 :(得分:0)
您无需在ACT_HI_PROCINST
抽象类中定义类型T
。您应该按照以下步骤进行操作:
Location
答案 2 :(得分:0)
scala编译器无法知道类type T <: Location
中定义的Location
与Route的类型参数[T <: Location]
的类型相同。
我认为你必须要签署def distance(...)
的签名。我不确定,但如果你将T定义为Location的类型参数:
abstract class Location[T <: Location[T]](val name: String) {
def distance[T](that: T): Double
}