正在加载图片...
1186 GENERICITY VERSUS INHERITANCE SB.5 Emulating constrained genericity(2) It is possible to emulate constrained genericity through inheritance and unconstrained genericity,by using wrapper classes and the corresponding wrapper objects. But we are again paying a price:we need to reintroduce wrapper classes such as INTEGER COMPARABLE.This is less shocking than in the earlier solution,because then we had to pay that price for the unconstrained case as well,even though it is conceptually very simple.Here it seems easier to justify the need for wrapper classes and objects since constrained genericity is a relatively sophisticated idea. Based on these observations,the notation of this book and compilers for it did not Exercise 19.5,page initially-for a little over two years,late 1985 to early 1988-have special support for 422of[M1988]. constrained genericity.The first edition of this book mentioned the possibility of such Later printings men- tioned that the exten- support,proposing as an exercise the exact design of an appropriate language construct. sion had been But it did not take very long afterwards to realize that most applications were not ready to integrated into the pay the price of wrapper classes and objects,and to integrate the exercise's solution into language. the notation;the compilers soon followed. The notation in question is,of course,the one earlier chapters have used to specify constrained genericity,as in elass MATRIX [G->RING_ELEMENT]... and elass SORTABLE LIST [G->COMPARABLE]... where RING ELEMENT and COMPARABLE are the original versions,deferred and non- generic.As noted in the first presentation of this notation in an earlier chapter,it is a remarkable combination of genericity and inheritance,avoiding all the extra baggage of earlier solutions: We do not need,like Ada,to use routines as generic parameters (with clauses).Only types can be generic parameters;this is simple,consistent and easy to learn. We do not need any special wrapper classes and objects.If you want a matrix of integers,you declare it as MATRIX [INTEGER]and use plain integers to set and retrieve its elements;if you want a sortable list of strings,you declare it as SORTABLE LIST [STRING]and use plain strings. The semantics,as you will remember,is that G represents not an arbitrary type any more,but a type that must conform to the constraint (be based on a descendant class).A generic derivation such as MATRIY [T]is valid if and only if 7 is such a type;this is true of INTEGER but not,for example,of STRING.Similarly,STRING will inherit from COMPARABLE and hence will be acceptable as an actual generic parameter for the class SORTABLE L/ST;but this is not true of a class COMPLEX (for complex num bers)which has no associated order relation.The symbol->was chosen,as you will also remember, to evoke the arrow of inheritance diagrams.1186 GENERICITY VERSUS INHERITANCE §B.5 But we are again paying a price: we need to reintroduce wrapper classes such as INTEGER_COMPARABLE. This is less shocking than in the earlier solution, because then we had to pay that price for the unconstrained case as well, even though it is conceptually very simple. Here it seems easier to justify the need for wrapper classes and objects since constrained genericity is a relatively sophisticated idea. Based on these observations, the notation of this book and compilers for it did not initially — for a little over two years, late 1985 to early 1988 — have special support for constrained genericity. The first edition of this book mentioned the possibility of such support, proposing as an exercise the exact design of an appropriate language construct. But it did not take very long afterwards to realize that most applications were not ready to pay the price of wrapper classes and objects, and to integrate the exercise’s solution into the notation; the compilers soon followed. The notation in question is, of course, the one earlier chapters have used to specify constrained genericity, as in class MATRIX [G –> RING_ELEMENT] … and class SORTABLE_LIST [G –> COMPARABLE] … where RING_ELEMENT and COMPARABLE are the original versions, deferred and non￾generic. As noted in the first presentation of this notation in an earlier chapter, it is a remarkable combination of genericity and inheritance, avoiding all the extra baggage of earlier solutions: • We do not need, like Ada, to use routines as generic parameters (with clauses). Only types can be generic parameters; this is simple, consistent and easy to learn. • We do not need any special wrapper classes and objects. If you want a matrix of integers, you declare it as MATRIX [INTEGER] and use plain integers to set and retrieve its elements; if you want a sortable list of strings, you declare it as SORTABLE_LIST [STRING] and use plain strings. The semantics, as you will remember, is that G represents not an arbitrary type any more, but a type that must conform to the constraint (be based on a descendant class). A generic derivation such as MATRIX [T] is valid if and only if T is such a type; this is true of INTEGER but not, for example, of STRING. Similarly, STRING will inherit from COMPARABLE and hence will be acceptable as an actual generic parameter for the class SORTABLE_LIST; but this is not true of a class COMPLEX (for complex numbers) which has no associated order relation. The symbol –> was chosen, as you will also remember, to evoke the arrow of inheritance diagrams. Emulating constrained genericity (2) It is possible to emulate constrained genericity through inheritance and unconstrained genericity, by using wrapper classes and the corresponding wrapper objects. Exercise 19.5, page 422 of [M 1988]. Later printings men￾tioned that the exten￾sion had been integrated into the language
<<向上翻页向下翻页>>
©2008-现在 cucdc.com 高等教育资讯网 版权所有