我正在从书Learning Scala开始练习,一个问题是:
创建一个容器类,其中包含一个实例和一个 参数化类型的实例。构造函数应该采用 可变数量的实例(例如,字符串或整数或任何其他 参数化类型),可以使用vararg参数实现。
我想出了以下内容:
$scope.lineTotal = function(line){
var markup = 1 + (line.markupPct / 100);
var discount = 1 - (line.discountPct / 100);
var lineTotal = line.price * discount * markup * line.qty;
$scope.newArray.push(lineTotal);
return lineTotal;
}
到目前为止,这么好。问题在于测试此代码。使用Scala Test和自定义匹配器的以下测试无法编译,更具体地说是sealed abstract class MyList[A]
sealed class MyNil[A] extends MyList[A]
sealed case class Cons[A](h: A, t: MyList[A]) extends MyList[A]
object MyNil {
def apply[A] = new MyNil[A]
}
object MyList {
def apply[A](items: A*): MyList[A] = {
items match {
case h :: t => Cons[A](h, apply(t: _ *))
case _ => MyNil[A]
}
}
}
方法。你能帮我理解为什么吗?
isEqual
修改1 : 根据请求包含IntelliJ的所有编译错误消息:
class MyListSpec extends FlatSpec with Matchers {
"MyList" should "be instantiated as expected" in {
val inputAndOutput = Table(
("ip", "op"),
(Nil, MyNil[Int]),
(List(1), Cons[Int](1, MyNil[Int])),
(List(1, 2), Cons[Int](1, Cons[Int](2, MyNil[Int]))),
(List(1, 2, 3), Cons[Int](1, Cons[Int](2, Cons[Int](3, MyNil[Int]))))
)
forAll(inputAndOutput) { (ip, op) =>
val o = MyList(ip: _ *)
println(o)
o should equal(op)
}
}
def equal[Int](right: MyList[Int]) = new MyListMatcher(right)
}
class MyListMatcher[Int, A <: MyList[Int]](val right: A) extends Matcher[A] {
override def apply(left: A): MatchResult = {
MatchResult(
isEqual(left),
s"""MyList $left did not match "$right"""",
s"""MyList $left matched "$right""""
)
}
def isEqual[A <: MyList[Int]](left: A) = {
left match {
case _: MyNil[Int] if right.isInstanceOf[MyNil[Int]] => println("Both are Nil."); true
case Cons[Int](h, t) if right.isInstanceOf[Cons[Int]] => {
println("Both are Cons.")
left == right
}
case _ => println("No match."); false
}
}
}
答案 0 :(得分:1)
回答我自己的问题,以下测试代码有效。问题是在方法Int
中不包含Cons
类型参数和isEqual
案例。
class MyListSpec extends FlatSpec with Matchers {
"MyList" should "be instantiated as expected" in {
val inputAndOutput = Table(
("ip", "op"),
(Nil, MyNil[Int]),
(List(1), Cons[Int](1, MyNil[Int])),
(List(1, 2), Cons[Int](1, Cons[Int](2, MyNil[Int]))),
(List(1, 2, 3), Cons[Int](1, Cons[Int](2, Cons[Int](3, MyNil[Int]))))
)
forAll(inputAndOutput) { (ip, op) =>
val o = MyList(ip: _ *)
println(o)
o should equal(op)
}
}
def equal(right: MyList[Int]) = new MyListMatcher(right)
}
class MyListMatcher(val right: MyList[Int]) extends Matcher[MyList[Int]] {
override def apply(left: MyList[Int]): MatchResult = {
MatchResult(
isEqual(left, right),
s"""MyList $left did not match "$right"""",
s"""MyList $left matched "$right""""
)
}
def isEqual(left: MyList[Int], right: MyList[Int]): Boolean = {
left match {
case _: MyNil[Int] if right.isInstanceOf[MyNil[Int]] => println("Both are Nil."); true
case Cons(h, t) if right.isInstanceOf[Cons[Int]] => {
println("Both are Cons.")
val r = right.asInstanceOf[Cons[Int]]
h == r.h && isEqual(t, r.t)
}
case _ => println("No match."); false
}
}
}
答案 1 :(得分:1)
您的代码存在问题:
def equal[Int](right: MyList[Int]) = new MyListMatcher(right)
<强> TL; DR 强>
改变这个:
class MyListMatcher[Int, A <: MyList[Int]](val right: A) extends Matcher[A] {
对此:
class MyListMatcher[A <: MyList[Int]](val right: A) extends Matcher[A] {
完整说明
您遇到的问题仅仅是Scala编译器试图找出您的新MyListMatcher
实例应该是什么类型的参数。
因为你的MyListMatcher
类是一个带有两个参数的类型构造函数(一个是硬编码为Int而另一个是从构造函数参数推断出来的),所以Scala编译器会看到这个并假设第一个参数是没什么,因为它没有在equal
方法中指定。
只需删除第一个Int类型参数,您的问题就会消失