title: Referring to abstract type outside of trait for class construction
body: <p>Premise:</p>
  
  <p>I want to separate the information necessary to instantiate a class from the information necessary to "run" the class. However, the information neccesary to "run" the class may differ from class to class. Thus, I imagine the class "has" specific information to run it, and the two go together.</p>
  
  <p>Here is an example of my code:</p>
  
  <pre><code>trait Machine {
    type Params &lt;: BaseParams
  
    def start(machineParams: Params): Unit
  }
  
  trait BaseParams {
    def speed: Int
    def power: Int
  }
  
  class FlyingMachine() extends Machine {
    type Params = FlyingParams
  
    override def start(machineParams: Params): Unit = {
      println(s"I'm flying with $machineParams")
    }
  }
  
  trait FlyingParams extends BaseParams {
    def height: Int
  }
  
  
  abstract class MachineOwner{
  
    val machine: Machine
  
    def params: machine.Params
  
    def startMachine(): Unit = {
      machine.start(params)
    }
  }
  </code></pre>
  
  <p>This compiles, passes tests, I'm happy.</p>
  
  <p>Problem: I'm using <code>val machine: Machine</code> in order to define <code>def params: machine.Params</code>. I've been told to make this a <code>def</code> to let the implementer have more freedom. If I do so, I can no longer refer to <code>machine.Params</code></p>
  
  <p>At this point, I'm at a loss for how to continue. I keep thinking that if this should be a <code>def</code> and definitely not a <code>val</code>, then my architecture is wrong. </p>
  
  <p>So</p>
  
  <ol>
  <li>Is my approach to this problem wrong, given the premise I set out with? </li>
  <li>If it's not wrong, is there a way to still achieve this while using <code>def</code> instead of <code>val</code> in the <code>MachineOwner</code> class? </li>
  </ol>
  
  <p><strong>EDIT</strong> 
  Given Alexey Romanov's answer, the last bit of the code would look like this</p>
  
  <pre><code>abstract class MachineOwner{
  
    type Params1 &lt;: BaseParams
  
    def machine: Machine { type Params = Params1 }
  
    def params: Params1
  
    def startMachine(): Unit = {
      machine.start(params)
    }
  }
  
  class FlyingMachineOwner(
    machine: FlyingMachine
  ) extends MachineOwner {
  
    override type Params1 = FlyingParams
  
    override def params = FlyingParams(1,1,1)
  }
  </code></pre>
  
  <p>But this doesn't compile because it expects an override specifically for <code>def machine: Machine { type Params = Params1 }</code>. How does one define that?</p>