Path: news.daimi.aau.dk!news.uni-c.dk!sunic!trane.uninett.no!eunet.no!nuug!EU.net!uunet!munnari.oz.au!ariel.ucs.unimelb.EDU.AU!ariel.ucs.unimelb.EDU.AU!law From: law@tauon.ph.unimelb.edu.au (Lachlan Witham) Newsgroups: comp.lang.beta Subject: Restricting enter parameter types in Subclasses Followup-To: comp.lang.beta Date: 19 Sep 1994 06:25:23 GMT Organization: University of Melbourne Lines: 150 Distribution: world Message-ID: Reply-To: law@tauon.ph.unimelb.edu.au NNTP-Posting-Host: tauon.ph.unimelb.edu.au Here's a meaty problem for all you BETA coding experts out there. Say I want to define an abstract class "Number", the root class of a numeric type hierarchy. Objects of the type "Number" should be able to take a reference to a number of the same type as an entry parameter. Stealing the interface of the "container" abstract class and modifying I might have: Number : (# << attributes >> dimension :< (# dim: @integer do INNER exit dim #) copyIn :< (# other: ^Number enter other[] do INNER #) enter (# other: ^Number enter other[] (* copy contents of other into THIS(number) *) do other -> copyIn #) do INNER exit THIS(number)[] #) Now I define two subclasses of Number, Scalar (also abstract) and Vector: Scalar : Number (# << more attributes >> dimension :: (# 1 -> dim #) copyIn ::< (# do (* how to copy one scalar type to another *) (* NOTE: not sure if following comparison of patterns is correct way *) (if other.Struc // Real then (if this(scalar).Struc // Real then other.getVal->value // Complex then 1->other.getVal->value if) // Complex then (if this(scalar).Struc // Real then other.getVal->value[1] // Complex then (for i:2 repeat i->other.getVal->value[i] for) if) if) #) do INNER #) Vector : Number (# value[3] : @Scalar << more attributes >> dimension :: (# 3 -> dim #) copyIn ::<(# do (for i:3 repeat other.getval(i) -> value[i] #) getVal : (# index: @integer enter index exit value[index] #) do INNER #) Subclasses of Scalar might be Real and Complex defined as such: Real : Scalar (# value: @real << more attributes >> getVal : (# exit value #) do INNER #) Complex : Scalar (# value[2] : @real << more attributes >> getVal : (# index: @integer enter index exit value[index] #) do INNER #) Now say we create some instances of these classes: r: @Real; c: @Complex; v: @Vector Then the following assignments should work without a hitch (good): r -> c c -> r but the following assignments should not be allowed (bad) v -> r; r ->v; v -> c; c -> r; but are in this program because the enter parameter of Number is only qualified by the class pattern "Number". i.e. enter (# other: ^Number enter other do other->copyIn #) The assignments only fail when the "copyIn" procedure is called. One solution to try is to qualify the reference variable "other" in the "enter" and "copyIn" patterns inside Number with enter (# other: ^THIS(number).Struc enter other do ... #) and likewise for "copyIn". This should (if it's legal?) make sure that any numeric object can only be passed another numeric object of its own concrete type. That is, a Real can only be passed another Real, a Vector to a Vector, etc. BUT, this doesn't allow a Real to be assigned to a Complex and vice-versa, which I want to be allowed. And finally to my question :-). Is it possible to futher restrict in a subclass an enter parameter declared in its superclass? Are there any other (relatively neat) solutions people can see to my dilemma? Any advice and ideas gratefully received (including syntax bugs) Cheers, Lachlan ------------------------------------------------------------------- Lachlan Witham law@tauon.ph.unimelb.edu.au PhD student Micro Analytical Research Centre School of Physics University of Melbourne, Australia -- ------------------------------------------------------------------- Lachlan Witham law@tauon.ph.unimelb.edu.au PhD student Micro Analytical Research Centre School of Physics University of Melbourne, Australia