Search code examples
scalaoopencapsulationtype-members

When should you use access modifiers for type members?


class EG {
  private[this] type TypeMember = A
  private[this] var field: Int = 0
}

It is possible to specify access modifiers for type members just like fields. In case of OOP is is well understood that encapsulation of fields does provide benefit prevent unintended sharing of state and restricting modification of state. As far as I know type members are only found in Scala and in many places they are just defined as public hence use of access modifiers on type members is not that well understood as in the case of fields. Type members do not hold any state like a variable or field. Since it does not hold a value it cannot be mutated. So my question is what are the places you should restrict access to a type member (define a type member as private or protected)?


Solution

  • Making a type member declaration private without providing a definition is not only useless but also not allowed by the compiler

    scala> class Foo { private[this] type T }
    <console>:11: error: abstract member may not have private modifier
           class Foo { private[this] type T }
    

    If you define the type member instead, then there may be some legitimate use cases.

    Example, private type alias:

    trait Foo {   
      private[this] type T = String
    }
    

    In this case the type T only exists inside the class. It may be useful for providing a shorter name for a type only in the context of the implementation.

    Another example, private renaming of type parameter

    trait Foo[Key] {
      private[this] type K = Key
    }
    

    with roughly the same use case.

    About making it protected, it may also make sense. Example:

    trait Foo {
      protected[this] type V
    
      def foo(v: V): V
    }
    

    which defines an interface consisting of a method working on an not-yet-specified type V, and then:

    class Bar extends Foo {
      type V = String // actually defining the type
      def foo(v: V): V = v 
    }