1

I have a class A and factory functions using apply method.

object A { def apply(a:String) {... new A} def apply(a:Int) {... new A} ... } class A(...) { ... } 

When I have a subclass B from A with the same factory methods. I have the same apply methods that generates B.

object B { def apply(a:String) {... new B} // duplication def apply(a:Int) {... new B} // duplication ... } class B(...) extends A { ... } 

Can I reuse the apply methods from A in B?

5
  • is the signature of the constructors of classes A and B the same? Commented Apr 10, 2016 at 20:06
  • @Edurardo: It's almost the same except that one parameter is missing in B, as A sets the parameter to true. Commented Apr 10, 2016 at 20:21
  • how will you discriminate when you need an A or a B instance? Commented Apr 10, 2016 at 20:35
  • @maasg: apply in object works as an object factory, so you can call A(..) or B(..) whatever necessary. Commented Apr 10, 2016 at 20:41
  • yes, requiring you to duplicate the code, which is what you want to avoid. I was thinking in terms of object FooFactory that could create A or B instances depending on some criteria. Commented Apr 10, 2016 at 20:43

1 Answer 1

2

One way to do this is to define a mixin trait that contains the common methods, which will depend on an abstract factory function. Then, the companion objects can extends such mixin, only implementing the specific way to create the corresponding instance.

An example:

trait FooFactory[T] { def make(s:String, i:Int): T def apply(s:String):T = make(s, 0) def apply(i:Int):T = make("", i) } class A(s:String = "", i:Int = 0) { def foo:String = s+i override def toString() :String = s"[$foo]" } // object A { // def apply(a:String): A = { new A(s=a)} // def apply(a:Int): A = { new A(i=a)} // } object A extends FooFactory[A] { def make(s:String, i:Int) = new A(s,i) } class B(s:String = "") extends A(s,-1){ override def foo:String = s+":"+super.foo } // object B { // def apply(a:String):B = { new B(a)} // def apply(a:Int):B = { new B(a.toString)} // } object B extends FooFactory[B] { def make(s:String, i:Int) = new B(s) } 

If you need access to specific methods of the target class hierarchy, you can constrain the type to that class of its subtypes.

trait FooFactory[T <: A] { def make(s:String, i:Int): T def apply(s:String): T = make(s, 0).someAMethod() } 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer, I just added what was needed for my solution. You can edit or delete it if you don't like it.
@prosseek that's unusual, but I like the collaborative approach. I just adapted it to my usual style.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.