Skip to content

Extension of Inner Classes #17649

@ftucky

Description

@ftucky

Scala Version

3.2.2

Minimized Code

trait A:
	final class X

	extension (x:X) 
		def next: A#X

def foo(ax:A#X) =
	ax.next

Result

Compilation fails with value next is not a member of A#X.

Expectation

Would be elegant to let code compile.
For an inner projection P#T, (x:P#T).extensionMethod(args) would desugar into something similar to

{ val outer : P = x.$outer
  outer.extensionMethod(inner:outer.T)(args)
}

Rationale

In a pattern where the inner class is final but the outer class is open, it is elegant to create extensions which only make sense on the subclasses of the outer class.

class A:
	class X

class B extends A:
	extension (x:X) def foo : ...

So that bx:B#Xs have a foo method, while ax:A#Xs do not.

Today, a significant boiler plate is necessary:

class A:
	class X:
		def deflect[T](f: (a:A.this.type) => a.X => T) : T  = f(A.this)(this)

object B:
	extension (x:B#X) def foo = x.deflect(_.foo)

class B extends A:
	def foo(x:X) = ...
  • the deflect method is present in the innerclass, and must be left public.
  • Each extension method is declared twice, once in the companion object as extension, and once in the class as implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions