我正在执行以下函数从另一个函数返回一个新图形,但Scala将结果推断为图形,我希望它特别是图形,圆形等。 我怎么能推断这个特定的数字呢?我被告知使用泛型来解决它,这将是怎样的?
trait Figure {
def x:Int
def y:Int
}
case class Circle(x:Int, y: Int, radio: Double)
extends Figure
case class Rectangle(x:Int, y: Int, width: Int, high: Int)
extends Figure
object Motor {
def move[T](x: Int, y: Int, figure: T) :Figure = figure match {
case Circle(xPos, yPos, radio) => Circle(xPos+x, yPos+y, radio)
case Rectangle(xPos, yPos, width, high) => Rectangle(xPos+x, yPos+y, width, high)
}
}
答案 0 :(得分:2)
这是一个更简洁,也许是一个不那么令人生畏的版本的Sarvesh Kumar Singh使用类型类的建议。我认为这是最好的方法。它为您提供类型安全功能,同时让您保持基本类型非常简单。
trait Figure {
def x:Int
def y:Int
}
case class Circle(x:Int, y: Int, radius: Double) extends Figure
case class Rectangle(x:Int, y: Int, width: Int, height: Int) extends Figure
trait Movable[T] {
def move( x: Int, y: Int, movable: T ) : T
}
implicit final object CircleIsMovable extends Movable[Circle] {
def move( x: Int, y: Int, c: Circle ) = Circle( c.x + x, c.y + y, c.radius )
}
implicit final object RectangleIsMovable extends Movable[Rectangle] {
def move( x: Int, y: Int, r: Rectangle ) = Rectangle( r.x + x, r.y + y, r.width, r.height )
}
object Motor {
def move[T : Movable](x: Int, y: Int, movable: T) : T = implicitly[Movable[T]].move( x, y, movable )
}
则...
scala> Motor.move(10,10,Circle(0,0,1))
res1: Circle = Circle(10,10,1.0)
scala> Motor.move(10,10,Rectangle(0,0,1,1))
res2: Rectangle = Rectangle(10,10,1,1)
答案 1 :(得分:1)
您应该这样做,以便"move"
type
本身T
发生,并返回type
T
。但是编译器会抱怨你不确定是否返回T
因为T
的实际类型将被确定为使用move
而编译器没有证据确定它是Circle
,match-case
是运行时的东西。
这意味着您需要提供可以在编译时使用move
任何type
T
实例的证据。
import scala.language.implicitConversions
trait Figure {
def x:Int
def y:Int
}
case class Circle(x:Int, y: Int, radio: Double)
extends Figure
case class Rectangle(x:Int, y: Int, width: Int, high: Int)
extends Figure
现在,让我们构建所需的证据,用于“丰富”我们的Figure
实例
trait MoveSupport[F <: Figure] {
val f: F
def move(x: Int, y: Int): F
}
object MoveSupport {
class CircleMoveSupport(val f: Circle) extends MoveSupport[Circle] {
override def move(x: Int, y: Int): Circle = f.copy(x = f.x + x, y = f.y + y)
}
class RectangleMoveSupport(val f: Rectangle) extends MoveSupport[Rectangle] {
override def move(x: Int, y: Int): Rectangle = f.copy(x = f.x + x, y = f.y + y)
}
implicit def toCircleMoveSupport(circle: Circle) = new CircleMoveSupport(circle)
implicit def toRectangleMoveSupport(rectangle: Rectangle) = new RectangleMoveSupport(rectangle)
}
现在,我们可以使用这些证据“丰富”我们的Figure
类型以获得move
支持。
import MoveSupport._
val circle = Circle(1, 1, 1)
// circle: Circle = Circle(1,1,1.0)
val circle2 = circle.move(1, 1)
// circle2: Circle = Circle(2,2,1.0)
或者,您可以使用这些证据构建Motor
。
object Motor {
import MoveSupport._
def move[T <: Figure](x: Int, y: Int, figure: T)(implicit ev: T => MoveSupport[T]): T = figure.move(x, y)
}
val c = Circle(1, 1, 1)
// circle: Circle = Circle(1,1,1.0)
val c1 = Motor.move(1, 1, c)
// circle1: Circle = Circle(2,2,1.0)
答案 2 :(得分:0)
也许你所追求的是
object Motor {
def move[T <: Figure](x: Int, y: Int, figure: T): T = {
val moved = figure match {
case Circle(xPos, yPos, radio) => Circle(xPos+x, yPos+y, radio)
case Rectangle(xPos, yPos, width, high) => Rectangle(xPos+x, yPos+y, width, high)
}
moved.asInstanceOf[T]
}
}
答案 3 :(得分:0)
您可能需要考虑将move
的实现移动到各个类。下面是一个使用abstract types来使该方法返回对象类型的示例:
trait Figure {
def x: Int
def y: Int
type Self <: Figure
def move(dx: Int, dy: Int): Self
}
case class Circle(x: Int, y: Int, radius: Double) extends Figure {
type Self = Circle
def move(dx: Int, dy: Int): Circle = copy(x = x + dx, y = y + dy)
}
case class Rectangle(x: Int, y: Int, widht: Int, height: Int) extends Figure {
type Self = Rectangle
def move(dx: Int, dy: Int): Rectangle = copy(x = x + dx, y = y + dy)
}