Companion object as a factory in scala

I am just starting out with Scala and working on some tutorials. I came across a companion object and used them as a factory. I tried a few things. However, I do not get the following to work properly. I can’t shave my head.

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... 

Just trying to add two integers, for example, I defined them in methods ... Does anyone know what I'm doing wrong?

EDIT: I tried to wrap the next (working) class in a factory.

 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 cx //> res0: Int = 4 cy //> res1: Int = 6 
+4
source share
1 answer

I'm not quite sure what restrictions are imposed on you, for example, which classes should / should be private, but using F-limited polymorphism can be a step towards your desired solution.

 /* 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 

Please note that this will not help you if you want to hide your implementations, i.e. make them private and declare public interfaces using only a common Point , as others have already pointed out.

+1
source

Source: https://habr.com/ru/post/1484077/


All Articles