scala - What's the difference between `trait ValueHolder { type ValueType }` and `trait ValueHolder[T] {}` -
this question has answer here:
when read source code of liftweb, found trait declarations:
trait valueholder { type valuetype def get: valuetype } trait pvalueholder[t] extends valueholder { type valuetype = t }
my question is, following 2 trait declarations:
trait valueholder { type valuetype } trait valueholder[t] { }
i think equal each other, there difference between them? 1 can or offer 1 can't?
the first 1 called abstract type member
, second 1 close analog java generics, there not complete same. 2 different ways achieve same goal. martin odersky explained his interview, 1 reason having both abstract type members , generic type parameters orthogonality:
there have been 2 notions of abstraction: parameterization , abstract members. in java have both, depends on abstracting over. in java have abstract methods, can't pass method parameter. don't have abstract fields, can pass value parameter. , don't have abstract type members, can specify type parameter. in java have 3 of these, there's distinction abstraction principle can use kinds of things. , argue distinction arbitrary.
what did in scala try more complete , orthogonal. decided have same construction principles 3 sorts of members. can have abstract fields value parameters. can pass methods (or "functions") parameters, or can abstract on them. can specify types parameters, or can abstract on them. , conceptually can model 1 in terms of other. @ least in principle, can express every sort of parameterization form of object-oriented abstraction. in sense scala more orthogonal , complete language.
he described difference between abstract type members , generic type parameters can show in practice:
but in practice, when use type parameterization many different things, leads explosion of parameters, , usually, what's more, in bounds of parameters. @ 1998 ecoop, kim bruce, phil wadler, , had paper showed increase number of things don't know, typical program grow quadratically. there reasons not parameters, have these abstract members, because don't give quadratic blow up.
i think great , easy example given bill veners (the creator of scalatest):
// type parameter version trait fixturesuite[f] { // ... }
and
// type member version trait fixturesuite { type f // ... }
in either case, f type of fixture parameter pass tests, suite subclasses make concrete. here's example of concrete suite of tests needs stringbuilder passed each test, using type parameter approach:
// type parameter version class mysuite extends fixturesuite[stringbuilder] { // ... }
and here's example of concrete suite of tests needs stringbuilder passed each test using abstract type member approach:
// type member version class mysuite extends fixturesuite { type f = stringbuilder // ... }
for example, if want pass 3 different fixture objects tests, you'll able so, you'll need specify 3 types, 1 each parameter. type parameter approach choosen, suite classes have ended looking this:
// type parameter version class mysuite extends fixturesuite3[stringbuilder, listbuffer, stack] myhandyfixture { // ... }
whereas type member approach this:
// type member version class mysuite extends fixturesuite3 myhandyfixture { // ... }
so shows 2 approaches goal in achieving great modular abstraction. more on topic can read in this legendary paper on scalable components
Comments
Post a Comment