Skip to content

Instantly share code, notes, and snippets.

@mbloms
Last active February 6, 2018 16:13
Show Gist options
  • Save mbloms/78a45479493f57c4b97ddc6b3dfa69d8 to your computer and use it in GitHub Desktop.
Save mbloms/78a45479493f57c4b97ddc6b3dfa69d8 to your computer and use it in GitHub Desktop.
Forcing invariance with compiler-generated traits and classes.
trait Immutable
class A
class B extends A
sealed trait AImm extends A with Immutable
sealed trait BImm extends B with AImm with Immutable
final class APrim extends AImm
final class BPrim extends BImm
object Test {
var a: A = new A()
var b: A = new B()
var c: A = new APrim()
var d: A = new BPrim()
//Works
var dd: B = new BPrim()
var ddd: AImm = new BPrim()
var dddd: BImm = new BPrim()
//Does not work
//var ddddd: APrim = new BPrim()
}
trait Immutable
abstract class Maybe[+A]
case class Ingenting() extends Maybe[Nothing]
case class Just[+A](value: A) extends Maybe[A]
sealed trait OptionImm[+A] extends Maybe[A]
final class IngentingImm extends Ingenting with OptionImm[Nothing]
final class JustImm[+A](value: A) extends Just[A](value) with OptionImm[A]

The overriding method is covariant in the return type and invariant in the argument types. That means that the return type of the overriding method can be a subclass of the return type of the overridden method, but the argument types must match exactly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment