java - Why can't a generic interface be used as a type parameter? -




here java generic code programming language pragmatics, scott

interface chooser<t> {     public boolean better(t a, t b); } class arbiter<t> {     t bestsofar;     chooser<? super t> comp;      public arbiter(chooser<? super t> c) {         comp = c;     }     public void consider(t t) {         if (bestsofar == null || comp.better(t, bestsofar)) bestsofar = t;     }     public t best() {         return bestsofar;     } }  class casesensitive implements chooser<string> {     public boolean better(string a, string b) {         return a.compareto(b) < 1;     } } ... arbiter<string> csnames = new arbiter<string>(new casesensitive()); csnames.consider(new string("apple")); csnames.consider(new string("aardvark")); system.out.println(csnames.best()); // prints "apple" 

java requires code each generic class manifestly (self-obviously) type safe, independent of particular instantiation. means type of field comp—and in particular, fact provides better method—must statically declared. result, chooser used given arbiter instance must specified constructor parameter; cannot generic parameter. (we have used constructor parameter in c++; in java mandatory.)

  1. what "code each generic class manifestly (self-obviously) type safe, independent of particular instantiation" mean?
  2. why lead conclusion "the type of field comp—and in particular, fact provides better method—must statically declared"?
  3. what "statically declared" mean? opposed to?
  4. what when chooser used generic parameter in java (even though not correct)? want see looks wrong in java. "we have used constructor parameter in c++; in java mandatory" mean wrong way written in c++ way (i saw similar code in c ++ earlier in book, quoted in previous post)? following wrong code in java, implied "chooser cannot generic parameter":

    class arbiter<t, chooser> {     t bestsofar;     chooser comp;      public arbiter(chooser c) {         comp = c;     }     public void consider(t t) {         if (bestsofar == null || comp.better(t, bestsofar)) bestsofar = t;     }     public t best() {         return bestsofar;     } } 

thanks.

quick disclaimer: don't know c++ anywhere near know java. if did wrong in answer i'm happy correct it.

most of questions here can answered explaining important difference between java generics , c++ templates. java generics implemented type erasure means compiler transforms generic code in non-generic code removing references generics , inserting casts appropriate. example, might have generic code follows:

class holder<t> {     private t obj;     holder(t obj) { this.obj = obj; }     t get() { return obj; } }  holder<string> h = new holder<string>("hello"); string s = h.get(); 

and during compilation that's transformed in code more this:

class holder {     private object obj;     holder(object obj) { this.obj = obj; }     object get() { return obj; } }  holder h = new holder("hello"); string s = (string) h.get(); 

by contrast, c++ templates more sophisticated copy , paste. might start code this:

template<typename t> class holder {     t obj; public:     holder(t obj) : obj(obj) {}     t& get() { return obj; } };  holder<std::string> h{"hello"}; std::string& s = h.get(); 

and when holder<std::string>, compiler creates new class (called template instantiation) has t replaced std::string:

class holder_std_string {     std::string obj; public:     holder_std_string(std::string obj) : obj(obj) {}     std::string& get() { return obj; } }; 

the major implications of are:

  1. each template instantiation "knows" type argument inside class body.
  2. the compiler can generate different code different template instantiations.

for example, might observe in following method of c++ arbiter:

void consider(t* t) {     if (!best_so_far || comp(*t, *best_so_far)) best_so_far = t;     //                  ^^^^^^^^^^^^^^^^^^^^^^ note! } 

the method body expects template argument c has operator overload (), there's nothing template declaration indicates this. instead, c++ has duck typing via templates. template instantiation arbiter<string, case_sensitive> knows template argument case_sensitive , can therefore generate code calls overloaded () operator. can pass template argument long has overloaded () operator compatible expression calls it. if passed argument c didn't have overloaded () operator, template instantiation fail compile.

another interesting note c++ code didn't need pass case_sensitive object constructor because template instantiation knows how default construct 1 itself.

for question #4, making chooser type generic parameter in java this:

class arbiter<t, c extends chooser<? super t>> {     t bestsofar;     c comp;      public arbiter(c c) {         comp = c;     }     public void consider(t t) {         if (bestsofar == null || comp.better(t, bestsofar)) bestsofar = t;     }     public t best() {         return bestsofar;     } } 

however, note we've accomplished via bounded type variable c extends chooser<? super t> tells compiler c must subtype of chooser. how compiler knows it's possible call method comp.better(...) , method expression refers to. remember there's ever 1 arbiter class in java generic arbiters need share bytecode.

the c++ code has no such requirement because validity of expression comp(...) decided during instantiation of template.

what "statically declared" mean? opposed to?

in context means it's known @ compile-time. illustrate:

// know statically (at compile-time) // n type if number. void m(number n) {     // determine @ runtime     // actual type of n couple     // of different ways.     if (n instanceof double)         /* n double */;     // prints actual type of n.     system.out.println(n.getclass()); } 

types in c++ statically-known too. it's c++ templates implemented in way allows many things java generics don't allow.





wiki

Comments

Popular posts from this blog

Asterisk AGI Python Script to Dialplan does not work -

python - Read npy file directly from S3 StreamingBody -

kotlin - Out-projected type in generic interface prohibits the use of metod with generic parameter -