3

Is there any way to do anything like this:

scala> trait Foo { def f:Int=0 }
defined trait Foo

scala> class FooImpl extends Foo { override val f = 1 }
defined class FooImpl

scala> class Bar(foo:Foo) extends Foo{ import foo._ }
defined class Bar

scala> (new Bar(new FooImpl)).f
res2: Int = 0

scala> trait Foo { def f:Int }
defined trait Foo

scala> class Bar(foo:Foo) extends Foo{ import foo._ }
<console>:8: error: class Bar needs to be abstract, since method f in trait Foo of type => Int is not defined
       class Bar(foo:Foo) extends Foo{ import foo._ }
             ^

scala> 

...in a way that would result in a subclass overriding a parent method via import? Basically I think it would be interesting to be able to use composition without all the typing. Just curious if anything like this is possible.

nairbv
  • 4,045
  • 1
  • 24
  • 26
  • yeah I realize that, just wondering if there's any way to make something like this work. It could make composition easy on traits that have large numbers of abstract methods. – nairbv Sep 20 '13 at 21:33
  • 1
    Because I want the implementation from an existing instance... and in reality the trait might have 20+ methods. Composition in Scala, due to the size of most traits, generally requires lots and lots of typing. My hands get tired. – nairbv Sep 20 '13 at 21:58
  • 1
    You might want to look at the AutoProxy compiler plugin. This question has some info: [Proxies / delegates in Scala](http://stackoverflow.com/questions/3473309/proxies-delegates-in-scala) – DaoWen Sep 20 '13 at 22:08
  • @DaoWen That question's pretty old, but I did just add an answer that reflects more recent developments. I'd encourage others to do the same if there's been other work in this area. – Aaron Novstrup Sep 20 '13 at 23:23
  • @Brian `import` just brings symbols into your lexical namespace, and rightly so (imagine the confusion of having methods accidentally implemented for you because of a careless wildcard import). Delegates seem like a much more promising solution. In the meantime, though, you should consider whether "composition in Scala ... requires lots and lots of typing" or whether perhaps your use case calls for a different *type* of composition (see @Shadowlands answer). – Aaron Novstrup Sep 20 '13 at 23:41
  • @AaronNovstrup: yeah, I realize that doing this might not be a great design, was just wondering about any possible way of doing it, even if it were just for some quick hack where I wanted something to work temporarily mid-refactor. The proxy/delegates thing definitely looks cool! – nairbv Sep 21 '13 at 23:56

2 Answers2

3

What you are really asking for is a way to delegate method implementations to a member.

That issue has already been addressed here: Proxies / delegates in Scala

Basically, there is a way to do it using macros. An implementation can be found here: https://github.com/adamw/scala-macro-aop

The above provides a @delegate macro annotation that can be applied to a data member to cause the compiler to generate code to delegate method calls to that member. Note that macro annotations are an experimental feature planned for Scala 2.11, but you can use them with Scala 2.10 using the Macro Paradise compiler plugin.

Community
  • 1
  • 1
reggert
  • 732
  • 3
  • 10
  • This is just the sort of thing I was looking for. Since it's still just a proof-of-concept, I won't be able to use it in any production code, but I like that it exists, and I'll probably play around with it. Thanks! – nairbv Sep 21 '13 at 23:59
1

Self-typing can help here (depending on exactly how you will be working with these classes - this isn't composition of instances, more composition of types):

trait Foo { def f:Int }

trait FooImpl extends Foo { override val f = 1 } // Needs to be a trait to be mixed in.

class Bar {
  this: Foo =>  // This requires that any Bar instance must mix in a Foo (must 'be' a Foo)
}

Then you can instantiate and use your Bar instance similar to the following:

scala> (new Bar with FooImpl).f
res1: Int = 1
Shadowlands
  • 14,994
  • 4
  • 45
  • 43
  • Something like this could be helpful, but I can't say "with someAlreadyInstantiatedInstance" ... I was hoping to re-use the implementation that exists in a specified parameter. – nairbv Sep 21 '13 at 23:58