Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Try the following:</p> <p>package inputabstraction</p> <pre><code>abstract class Point[T](n:String){ def value: T val name = n } case class Input[T](n:String, value:T) extends Point[T](n) object testTypedCaseClass{ def test(){ val foo = Input("foo", "bar") println(foo) } } </code></pre> <p>A simple Application to check that it works:</p> <pre><code>import inputabstraction._ object TestApp extends Application{ testTypedCaseClass.test() } </code></pre> <p><strong>Explanation</strong></p> <p>The first mistake you are making is <code>case class Input[Type](n:String) extends Point(n){</code>. Point is a typed class, and so when you are calling the superclass constructor with <code>extends Point(n)</code> you need to specify the type of <code>Point</code>. This is done like this: <code>extends Point[T](n)</code>, where T is the Type you are planning to use.</p> <p>The second error is that you are both defining and declaring value:T here: <code>var value: Type = _</code>. In this statement, <code>_</code> is a value. Its value is <code>Nothing</code>. The scala compiler infers from this that <code>Point[T]</code> is <code>Point[Nothing]</code>. Thus when you attempt to set it to a type in the body of your <code>setValue</code> method, you must set it to <code>Nothing</code>, which is probably not what you want. If you attempt to set it to anything besides <code>Nothing</code>, you will get the type mismatch from above, because value is typed as <code>Nothing</code> due to your use of <code>_</code>.</p> <p>The third mistake is using <code>var</code> instead of <code>val</code> or <code>def</code>. <code>val</code> and <code>def</code> can be overridden interchangeably, which means that subtypes can override with either <code>val</code> or <code>def</code>, and the scala compiler will figure it out for you. It is best practice to define vals as functions using <code>def</code> in abstract classes and traits, because the initialization order of subtype constructors is a very difficult thing to get right (there is an <a href="http://jim-mcbeath.blogspot.com/2009/08/scala-class-linearization.html#rules" rel="nofollow">algorithm</a> for how the compiler decides how to construct a class from its supertypes). TL#DR === use def in supertypes. Case class parameters are automatically generate <code>val</code> fields, which, since you are extending a Point, will create a val value field that overrides the def value field in <code>Point[T]</code>.</p> <p>You can get away with all this <code>Type</code>||<code>T</code> abstraction in Scala because of type inference and the fact that <code>Point</code> is abstract, therefore making value extendable via val.</p> <p>The preferred way of doing dependency injection like this is the <a href="http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/" rel="nofollow">cake pattern</a>, but this example I have provided works for your use-case.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload