Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Puzzle -- exposing a public sub-member of private member with custom type

I would like to do something like this (example is simplified, but contains all the crucial pieces):

class Master
{
  type DataType = Int
  var counter : DataType = 0
}

class Slave(private val master : Master)
{
  val counter = master.counter  // (*)
}

And here (*) I get error:

private value master escapes its defining scope as part of type Slave.this.master.DataType

val counter = master.counter

I understand the error, but I don't understand the reason - the type is part of the class Master, not the object master, so it is important if the class is private, not an object. Well, at least in theory.

It is easy to make a quick workaround:

  val counter : Master#DataType = master.counter  

But I believe this is an explicit version of the exactly same code as before, it "only" takes more typing. Is this a feature then?

QUESTION:

Can a type (here DataType) be dependent of the object, and not the class (i.e. type definition per instance of the class) in Scala?

like image 902
greenoldman Avatar asked Jan 01 '12 20:01

greenoldman


1 Answers

You are wrong when you think

this is an explicit version of the exactly same code as before

Master#DataType and master.DataType are two different types.

master.DataType is the type of those DataType instances which have master as outer object. In other words, precisely what you ask, but obviously then master is part of the type, and the type can't be exposed if master isn't.

Master#DataType is the type of any DataType instance for any outer object (equivalent to Master.DataType in Java).

REPLY TO THE COMMENT:

Type members can be overridden in a subclass (including an anonymous subclass containing only one object), but only by a compatible type. And in your example DataType is already concrete in Master, so the only compatible class with it is itself. So something like

val a = new Master {
  override type DataType = String
}

won't typecheck, which makes sense: you'd get var counter: String = 0, which is nonsense. But

val a = new Master {
  override type DataType = Int
}

will work (but isn't too useful).

So it only ever makes sense to override abstract type members. But they are type-checked in the same way as inner classes, so a.DataType is not generally considered the same as b.DataType -- even if they can't actually be different!

like image 144
Alexey Romanov Avatar answered Nov 13 '22 15:11

Alexey Romanov