Alan Coromano
Alan Coromano

Reputation: 26048

Returning a nested class from a method

There is an error I don't understand:

class MyClass1 {
  private class MyClass1Internal(a: Int, b: Int, c: String, d: String)
  def method1 = {
    // doing something
    new MyClass1Internal(1, 2, "3", "4")
  }
}

an error

private class MyClass1Internal escapes its defining scope as part of type MyClass1.this.MyClass1Internal
[error]   def method1 = {
[error]       ^

What is it about and how do I get rid of it?

Upvotes: 1

Views: 122

Answers (2)

cmbaxter
cmbaxter

Reputation: 35463

MyClass1Internal is private and thus should never be able to be accessed outside of MyClass1, but method will return an instance of it outside this class (as it's public), thus breaking its defining scope.

I bet if you defined method as private it would fix this error. You could also make the nested class not be private.

One more thing, if you wanted other code be able to work with that class but not be able to instantiate it, then just make the constructor private and the class public like so:

class MyClass1 {
  class MyClass1Internal private[MyClass1](a: Int, b: Int, c: String, d: String)
  def method1 = {
    // doing something
    new MyClass1Internal(1, 2, "3", "4")
  }
}

Upvotes: 6

gzm0
gzm0

Reputation: 14842

The public API of MyClass1 uses a part of its private API (MyClass1Internal). This is bad, as another class does not know MyClass1Internal and hence cannot make sense of the return type of method1.

If you do not want to expose MyClass1Internal but still return an instance to it, you'll have to upcast method1's return type to something public. For example:

trait MyClass1Interface {
  def a: Int
}

class MyClass1 {
  private class MyClass1Internal(val a: Int, b: Int, c: String, d: String)
    extends MyClass1Interface
  def method1: MyClass1Interface = {
    // doing something
    new MyClass1Internal(1, 2, "3", "4")
  }
}

This allows you to hide the exact implementation of the interface in your class, but keep the method public. (Your interface can of course still be part of the class if you prefer that).

Upvotes: 1

Related Questions