I've found a solution using one factory object per Message subtype.
abstract class MessageFactory[M] {
def make(): M
}
class Message{
var name:String=""
def setName(newname:String) {name=newname}
def send()=println(name)
}
implicit object MessageMessageFactory extends MessageFactory[Message] {
def make()=new Message()
}
class SubMessage extends Message {
var t:String=""
def setType(newtype:String) {t=newtype}
override def send()=println(name+" ("+t+")")
}
implicit object SubMessageMessageFactory extends
MessageFactory[SubMessage] {
def make()=new SubMessage()
}
def sendMessage[T <: Message](setter:T=>unit)(implicit factory:
MessageFactory[T]) {
var msg:T=factory.make()
setter(msg)
msg.send()
}
sendMessage[Message] { m =>
m.setName("foo")
m.setName("bar")
}
sendMessage[SubMessage] { m =>
m.setType("count")
m.setName("Update")
}
I'd say you couldn't do it with less syntax, it's safe and it's very
readable. However, each message needs a factory method attaching to it
which is a little annoying, but very workable.
What do you think?
Also, a note to Scala writers - would it be possible to compile "new
T()", where T is a type variable, into a factory method like I've done
here?
One other thing: The technique you described below is not very safe,
since if you mistype the name of one of the parameters, the compiler
will give no error, but your code will not work (suppose you wrote "val
displaYYYName = somename", displayName will still equal null)
Robin
> > > I was under the impression that the
> > > ad-hoc-initialization-block-using-anonymous-subclass trick was the
> > > "standard way" to do this kind of thing in Scala. In your example, I
> > > infer that Message is a Java class, but if it was written in Scala,
> > > one idiom for initialization would be to declare abstract vals, like
> > > this:
> > >
> > > abstract class Message {
> > > val displayName:String
> > > val content:String
> > > }
> > >
> > > sw sendMessage (new Message {
> > > val displayName = somename
> > > val content = format("Hello, %s! %s!", displayName, somecontent)
> > > })
> >
> > Thanks for confirming that, I had no idea if it was a popular
> > technique with Scala. I myself try to avoid it, as it feels a little
> > intrusive and, well, 'blunt'. :) But it certainly is a smooth way.
> >
> >
> > > Anyway, I really liked your second example, using the pipe and the
> > > underscore closure shorthand together looks like a cool technique.
> >
> > Nice :) . Btw., if the method 'warn' wasn't overloaded, the syntax
> > could be reduced into just '"foo" | warn'. Although, I'm thinking the
> > name '|' may be a little confusing as it doesn't transform the
> > source.. (Instead, if we named map+filter to pipe, it would be shell
> > scripts all over again. :)
> >
> > But anyways, it's funny that there hasn't been more suggestions about
> > some standard ways for replacing this proprietary hack. I'm just a
> > Scala newbie still and I'm sure there's a lot of constructs and
> > syntactic tricks I'm not aware of.