trait Foo[T] { val foo: T} class A extends Foo[Unit]{ lazy val foo = println("Unit: called A.foo") } class B extends Foo[Unit]{ val foo = println("Unit: called B.foo") } trait Bar[T] { def foo: T} class C extends Bar[Unit]{ lazy val foo = println("Unit: called C.foo") } class D extends Bar[Unit]{ def foo = println("Unit: called D.foo") } object Test extends App { val a: Foo[Unit] = new A a.foo a.foo val b: Foo[Unit] = new B b.foo b.foo val c: Bar[Unit] = new C c.foo c.foo val d: Bar[Unit] = new D d.foo d.foo }