This page is no longer maintained — Please continue to the home page at www.scala-lang.org

2.8's named and default parameter in inheritance and overloading

3 replies
fanf
Joined: 2009-03-17,
User offline. Last seen 2 years 30 weeks ago.

Hello,

I would like to provides "copyWith" methods for my domain which allows
caller to override some copied object value.

Ideally, they could be called like that :
=========================
//clone
val parent1_clone = parent1.copyWith()
//copy parent1 and set a new value to the p var or val
val parent2 = parent1.copyWith( p = "foo" )

//copy child1 that extends Parent and set new value to p and c
val child2 = child1.copyWith(p = "foo", c = "bar")

=========================

And so, I thought I could build classes that would look like:
=========================
class Parent {
var p = ""
def copyWith( p : String = this.p ) = { ... }
}

class Child extends Parent {
var c = ""
def copyWith( p : String = this.p, c : String = this.c) = { ... }
}
=========================

It doesn't work for several reasons, among them scalac complains about
"multiple overloaded alternatives of method copyWith define default
arguments", and typing problem.

That seems to me like being a fairly common usecase for default and
named arguments (it is emphased in http://www.scala-lang.org/node/2075
for case classes), but I don't see how to make it work, and the SID
doesn't help me here.

Does anybody have ideas about how to provide such an API for my domain ?
Any helps, or pointer towards literature about that would be really
helpful.

Thanks,

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: 2.8's named and default parameter in inheritance and overl
1) Avoid subclassing.
2) Use case classes.
3) They already come with a "copy" method.

Cheers,

--j

On Sat, Oct 24, 2009 at 6:23 AM, Francois Armand <fanf42 [at] gmail [dot] com> wrote:
Hello,


I would like to provides "copyWith" methods for my domain which allows caller to override some copied object value.

Ideally, they could be called like that :
=========================
  //clone
  val parent1_clone = parent1.copyWith()
  //copy parent1 and set a new value to the p var or val
  val parent2 = parent1.copyWith( p = "foo" )

 //copy child1 that extends Parent and set new value to p and c
 val child2 = child1.copyWith(p = "foo", c = "bar")

=========================

And so, I thought I could build classes that would look like:
=========================
class Parent {
   var p = ""
   def copyWith( p : String = this.p ) = { ... }
}

class Child extends Parent {
   var c = ""
   def copyWith( p : String = this.p, c : String = this.c) = { ... }
}
=========================

It doesn't work for several reasons, among them scalac complains about "multiple overloaded alternatives of method copyWith define default arguments", and typing problem.

That seems to me like being a fairly common usecase for default and named arguments (it is emphased in http://www.scala-lang.org/node/2075 for case classes), but I don't see how to make it work, and the SID doesn't help me here.

Does anybody have ideas about how to provide such an API for my domain ?
Any helps, or pointer towards literature about that would be really helpful.

Thanks,

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: 2.8's named and default parameter in inheritance and overl

hi,

If default parameters are involved it makes it pretty difficult for
the compiler to tell which you mean, which does copyWith() call?

The typing problem might be solved with either this.type as the return
value or by using a type member (and refining the type down the
heirarchy). For type parameterisation you need type members.

Additionally factories, as per your blog post, are not polymorphic.
Instead I'd advise using virtual constructors, where the copy function
belongs to the objects (similar to your first approach). Each derived
class overrides the copy constructor providing the correct instance.

This can get a little twisted however if you have type members and
want both a class to be instantiated and to be derived from, then you
need a factory function to create the first instance and the virtual
constructor to call the factory function.

I've got a summary of sorts here :
http://code.google.com/p/scala-scales/wiki/VirtualConstructorPreSIP

Of course that doesn't solve the named / default parameter part of the
problem. I've not found a good way to use default parameters for
virtual constructors yet (given that the parameter list invariably
grows as the heirarchy deepens), I'd also like to know if there is a
good solution.

Hope that helps :-)

On Sat, Oct 24, 2009 at 2:23 PM, Francois Armand wrote:
> Hello,
>
>
> I would like to provides "copyWith" methods for my domain which allows
> caller to override some copied object value.
>
> Ideally, they could be called like that :
> =========================
>   //clone
>   val parent1_clone = parent1.copyWith()
>   //copy parent1 and set a new value to the p var or val
>   val parent2 = parent1.copyWith( p = "foo" )
>
>  //copy child1 that extends Parent and set new value to p and c
>  val child2 = child1.copyWith(p = "foo", c = "bar")
>
> =========================
>
> And so, I thought I could build classes that would look like:
> =========================
> class Parent {
>    var p = ""
>    def copyWith( p : String = this.p ) = { ... }
> }
>
> class Child extends Parent {
>    var c = ""
>    def copyWith( p : String = this.p, c : String = this.c) = { ... }
> }
> =========================
>
> It doesn't work for several reasons, among them scalac complains about
> "multiple overloaded alternatives of method copyWith define default
> arguments", and typing problem.
>
> That seems to me like being a fairly common usecase for default and named
> arguments (it is emphased in http://www.scala-lang.org/node/2075 for case
> classes), but I don't see how to make it work, and the SID doesn't help me
> here.
>
> Does anybody have ideas about how to provide such an API for my domain ?
> Any helps, or pointer towards literature about that would be really helpful.
>
> Thanks,
>
> --
> Francois Armand
> http://fanf42.blogspot.com
>

fanf
Joined: 2009-03-17,
User offline. Last seen 2 years 30 weeks ago.
Re: 2.8's named and default parameter in inheritance and overlo

Hello,

Please see comments below

On 25/10/2009 16:25, Chris Twiner wrote:
> Additionally factories, as per your blog post, are not polymorphic.
> Instead I'd advise using virtual constructors, where the copy function
> belongs to the objects (similar to your first approach). Each derived
> class overrides the copy constructor providing the correct instance.

I don't see how to make it works with default/name parameter. But
without that, it seems to be the way to go.

> I've got a summary of sorts here :
> http://code.google.com/p/scala-scales/wiki/VirtualConstructorPreSIP

Really interesting, I'll look carefully at it.

> [...] (given that the parameter list invariably
> grows as the heirarchy deepens), I'd also like to know if there is a
> good solution.

That is actually the problematic part. When I first heard about
Default/named parameter, I thought cloning/copying object would be the
perfect use case for them, but it seems that in their actual shape, it's
not a good idea. I'm going to continue to search a better use, but for
now, I thing there is just missing bits on them.

> Hope that helps :-)

It helped, thanks :)

--
Francois

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland