Path: news.daimi.aau.dk!news.uni-c.dk!sunic!trane.uninett.no!eunet.no!nuug!EU.net!howland.reston.ans.net!darwin.sura.net!wvnvms!marshall.wvnet.edu!marshall.edu!hathawa2 Newsgroups: comp.object,comp.lang.eiffel,comp.lang.sather,comp.lang.beta,comp.lang.modula3 Subject: Re: Cows, Hogs & Farms Message-ID: <1995Jan9.021043@hobbit> From: hathawa2@marshall.edu (Mark S. Hathaway) Date: 9 Jan 95 02:10:43 EDT References: <1995Jan3.223031@hobbit> <1995Jan4.191910.13968@schbbs.mot.com> Organization: Marshall University Nntp-Posting-Host: frodo.marshall.edu Lines: 123 Xref: news.daimi.aau.dk comp.object:23564 comp.lang.eiffel:7128 comp.lang.sather:1397 comp.lang.beta:205 comp.lang.modula3:3308 > In article <1995Jan4.191910.13968@schbbs.mot.com>, > shang@corp.mot.com (David L. Shang) writes: >> In article <1995Jan3.223031@hobbit> >> hathawa2@marshall.edu (Mark S. Hathaway) wrote: [ much deleted here and there throughout this post ] > In reality, we always have exceptions. We can use covariance to rule out a > general principle and use run-time type check for a few exceptions. As to > the animal example, it is clearly worthwhile to divide animals into > herbivires, carnivores and (?)(animals eating both food) according to the > type of their food. We can use covaraince. But it might be very hard to > rule out a general principle for the futher classification for a certain > number of animals. It's herbivore, carnivore & omnivore. Eats plants, meat & pizza with everything! :-) > We are not developing a commercial software for zoologists, are we? These > are only padagogical examples. Be wise to make things as simple as possible > -- just for the key points you want to say. I have created a few examples in the past which thoroughly confused people because they weren't realistic enough. I'm trying to avoid the sins of my past. >>> class field [FoodType <: plant] >>> function getCrop(): FoodType; >>> end field; >> Isn't a generic field which can grow any plant more correct? Doesn't the >> notation you've given tie one specific plant to the field and not allow for >> future crop rotations? Farmers plant different crops to avoid depleting >> the soil too much. > This is an abstract field. No object can be intantiated by the class > unless you associate it with a plant type. Yes, but after you've instantiated an object with a particular plant, can you then change the plant? >>> class farm [AnimalType <: herbivore] is >>> animals: list [MemberType = AnimalType]; >>> fields: list [MemberType = field [FoodType = AnimalType.FoodType]]; >>> function getRipeFood(): AnimalType.FoodType; >>> -- get the ripe food from one of its fields. >>> ... >>> end farm; >>> > class hog_farm is farm [AnimalType = hog]; > class cow_farm is farm [AnimalType = cow]; > Note that the generic classes I presented above are not conventional generic > classes. You cannot have this by Eiffel's generic class, which is not a real > class, and hence it is meaningless to discuss the subclass relationship > between a generic class and the class instantiated by the generic class. I like the looks of class farm above. It's quite similar to what I've been developing in pseudo-code. I've used "(param)" instead of "[param]" though. I'd certainly be interested to read further discussion on the differences between these classes and those of Sather & Eiffel. There seem to be some rather major differences. BTW, are these examples of yours in Cluster? >>> program farming is >>> c is cow_farm; >>> h is hog_farm; >>> begin >>> ... >>> for each animal in c.animals do animal.eat(aCorn); -- wrong! >>> for each animal in c.animals do animal.eat(aGrass); -- correct. >>> for each animal in c.animals do animal.eat (c.getRipeFood ()); >>> -- correct. >>> end farming. >>> Secondly, you could have an ill-structured heterogeneous farm where >>> various type of herbivores are raised at random fields. That is, there >>> is no relationship between a field type and a herbivore type: >>> >>> class farm is >>> animals: list [MemberType <: herbivore]; >>> fields: list [MemberType <: field]; >>> function getRipeFood(): plant; >>> -- get the ripe food from one of its fields. >>> end farm; >> Why do you say "animals: list [MemberType <: herbivore];" >> instead of animals: list [ herbivore ]; > The latter is equivalent to: > > animals: list [ MemberType = herbivore ]; > > where "animals" is not a polymorphic (heterogeneous) variable. Are you saying that without "<:" it won't recognize "herbivore" as a class from which to inherit; and that in the second case it would simply "think" "animals: list [ herbivore ];" refers to some "herbivore" other than the class? >>> procedure self_farming is (f is in farm) >>> begin >>> ... >>> for each animal in f.animals do animal.eat(f.getRipeFood ()); -- wrong! >>> for each animal in f.animals do >>> plant food := f.getRipeFood(); >>> when typeof(animal).Foodtype = typeof(food) do >>> animal.eat(food); -- correct >>> end >>> end self_farming. Looks decent. But, it doesn't make me want to take up farming. :-) Mark S. Hathaway