Private mixins

178 views
Skip to first unread message

marius a. eriksen

unread,
Nov 2, 2012, 12:37:58 PM11/2/12
to scala-...@googlegroups.com
One thing that I've had the need for several times now is to make “private” mixins. That is, I want to use mixins for composition but not for typing.

Let's say I have traits

  trait Iface { ... }
  trait Behavior { self: Iface => ... }

I'd like to be able to write

  class Impl extends Iface with private Behavior { ... }

so that `Behavior' does not become part of `Impl's type. IOW, I cannot now write:

  val b: Behavior = new Impl

Why do I want this? Because I don't want anyone to rely on this behavior: the fact that I'm mixing in Behavior is only an implementation artifact, and users of `Impl' shouldn't be allowed to rely on this.

marius.

Dennis Haupt

unread,
Nov 2, 2012, 12:44:02 PM11/2/12
to marius a. eriksen, scala-...@googlegroups.com
try this:

class MeOpenPublicClass {}

class MySecretPackagePrivateOrSoImplementation extends ThatOneTrait {}

and only pass yourself around as the upper class



-------- Original-Nachricht --------
> Datum: Fri, 2 Nov 2012 09:37:58 -0700 (PDT)
> Von: "marius a. eriksen" <marius....@gmail.com>
> An: scala-...@googlegroups.com
> Betreff: [scala-debate] Private mixins

marius a. eriksen

unread,
Nov 2, 2012, 1:10:34 PM11/2/12
to scala-...@googlegroups.com, marius a. eriksen
How would this work exactly? I'm trying to avoid proxying/forwarding..

Aleksey Nikiforov

unread,
Nov 2, 2012, 3:59:23 PM11/2/12
to marius a. eriksen, scala-debate
What Dennis is hinting at is something like the following arrangement:

package code {
  abstract class MyClass private[code] ()
  object MyClass { def apply() :MyClass = new MyClassImpl() }

  private[code] trait Behavior { ... }
  private[code] class MyClassImp extends MyClass with Behaviour
}

Public API only exposes MyClass, and MyClass factory. The atual implementation MyClassImp is hidden, so the fact that it extends Behaviour is not exposed.

This pattern is often used in Java to hide implementations. Have a look at the source code of java.nio.ByteBuffer as an example.

marius a. eriksen

unread,
Nov 2, 2012, 4:29:23 PM11/2/12
to scala-...@googlegroups.com, marius a. eriksen
Oh, sure, you can always do this, but you don't always have a choice, either because (1) you're modifying a class that is already public, or (2) you want to enable subclassing.

marius.

Julien Richard-Foy

unread,
Nov 3, 2012, 8:33:42 AM11/3/12
to scala-...@googlegroups.com, marius a. eriksen
@marius You can do as you would in any OO:

def createA: A = new A with B with C

The key idea is to explicitly annotate the return type of `createA` with `A`, to hide the fact that `B` and `C` are mixed in.

marius a. eriksen

unread,
Nov 3, 2012, 12:27:42 PM11/3/12
to Julien Richard-Foy, scala-...@googlegroups.com
I understand this. My particular desire was to be able to avoid that for the reasons outlined in my previous email. 

friedrich esser

unread,
Nov 3, 2012, 7:13:46 PM11/3/12
to scala-...@googlegroups.com, marius a. eriksen
What do you mean by "hide":

scala> class A
defined class A

scala> trait B
defined trait B

scala> trait C
defined trait C

scala> def createA: A = new A with B with C
createA: A

scala> val a= createA
a: A = $anon$1@12b512ef

scala> a.isInstanceOf[B]
res0: Boolean = true

scala> a.isInstanceOf[C]
res1: Boolean = true


Esser

marius eriksen

unread,
Nov 3, 2012, 11:40:47 PM11/3/12
to friedrich esser, scala-...@googlegroups.com, marius a. eriksen
Again — as I've indicated multiple times — I'm specifically not looking for hiding via a factory method.

marius.

Roland Kuhn

unread,
Nov 4, 2012, 2:57:51 AM11/4/12
to marius eriksen, friedrich esser, scala-...@googlegroups.com, marius a. eriksen
Hi Marius,

what about making the private traits protected[whatever]? That should prevent anyone not in that package from doing anything with them. And if someone must be naughty, they can always put some if their code into whatever package.


Regards,

Roland Kuhn
Typesafe — The software stack for applications that scale
twitter: @rolandkuhn

marius a. eriksen

unread,
Nov 4, 2012, 10:07:03 AM11/4/12
to scala-...@googlegroups.com, marius eriksen, friedrich esser, marius a. eriksen
Aha, interesting. I had thought that a protected annotation would prevent me from constructing a public class that mixes it in because it exports the protected trait.

It does mean that you have to control the mixin, though, you can't “re-protect” it; ie. this compiles:

package foo {
  trait Mixin
}

package bar {
  protected[bar] trait ProtectedMixin extends foo.Mixin
  class Bar extends ProtectedMixin
}

package baz {
  object Baz {
    val inst = new bar.Bar
    val mixin: foo.Mixin = inst

Aleksey Nikiforov

unread,
Nov 4, 2012, 11:09:15 AM11/4/12
to marius a. eriksen, scala-debate, marius eriksen, friedrich esser
Similar arrangement in my library has stopped working when upgrading to Scala 2.9. Then I was told that inheriting protected members is not allowed. If compiler lets you do so, it is a bug.

This is one of those gray areas that can be changed later, I would not rely on it.
Reply all
Reply to author
Forward
0 new messages