Сопутствующий объект как фабрика в Scala
Я только начинаю со Scala и работаю над некоторыми уроками. Я наткнулся на объект-компаньон и использовал их как фабрику. Я попробовал несколько вещей. Однако я не получаю следующее, чтобы работать должным образом. Не могу получить мою голову вокруг этого..
import math._
abstract class Point{
// ...
}
object Point{
private class PointInt(val x:Int,val y:Int) extends Point{
def +(that:PointInt) = new PointInt(this.x + that.x, this.y + that.y)
def distance(that:PointInt) =
sqrt(pow((this.x - that.x), 2) + pow((this.y - that.y), 2))
}
private class PointDouble(val x:Double,val y:Double) extends Point{
def +(that:PointDouble) = new PointDouble(this.x + that.x, this.y + that.y)
def distance(that:PointDouble) =
sqrt(pow((this.x - that.x), 2) + pow((this.y - that.y), 2))
}
def apply(x:Int,y:Int):Point = new PointInt(x,y)
def apply(x:Double,y:Double):Point = new PointDouble(x,y)
}
val a = Point(1,2)
val b = Point(3,4)
val c = a+b // does not work...
Просто пытаюсь сложить две целочисленные точки, как я определил в методах... Кто-нибудь знает, что я делаю неправильно?
РЕДАКТИРОВАТЬ: я пытался обернуть следующий (рабочий) класс на фабрике.
class Point(val x:Int,val y:Int){
def +(that:Point) = new Point(this.x + that.x, this.y + that.y)
def distance(that:Point) = sqrt(pow((this.x - that.x),2) + pow((this.y - that.y),2))
}
val a = new Point(1,2) //> a : week1.OU2.Point = week1.OU2$Point@73e48fa7
val b = new Point(3,4) //> b : week1.OU2.Point = week1.OU2$Point@677bb8fe
val c = a+b //> c : week1.OU2.Point = week1.OU2$Point@6bae60c5
c.x //> res0: Int = 4
c.y //> res1: Int = 6
1 ответ
Я не совсем уверен, какие ограничения на самом деле наложены на вас, например, какие классы должны / должны быть частными, но использование F-ограниченного полиморфизма может стать ступенькой к вашему желаемому решению.
/* Simplified interface (adding sqrt is straight-forward) */
abstract class Point[P <: Point[P]] {
def +(that: P): P
}
/* Two implementations */
class PointInt(val x:Int,val y:Int) extends Point[PointInt] {
def +(that:PointInt) = new PointInt(this.x + that.x, this.y + that.y)
}
class PointDouble(val x:Double,val y:Double) extends Point[PointDouble] {
def +(that:PointDouble) = new PointDouble(this.x + that.x, this.y + that.y)
}
/* Companion object */
object Point {
def apply(x:Int,y:Int) = new PointInt(x,y)
def apply(x:Double,y:Double) = new PointDouble(x,y)
}
/* Use cases */
val a = Point(1,2)
val b = Point(3,4)
val c = a+b // ok
val d = Point(1.0, 2.5)
val e = c+d // error: type mismatch
Однако обратите внимание, что это не поможет вам, если вы захотите скрыть свои реализации, то есть сделать их закрытыми и объявить открытые интерфейсы с помощью универсального Point
только - как уже указывали другие.