Inheritance/Single: Difference between revisions
{{omit from|PARI/GP}} |
Go solution |
||
Line 323:
end module anim
</lang>
=={{header|Go}}==
Go eschews most trappings of inheritance, yet it's anonymous field feature allows building one struct type upon another and accessing fields of "embedded" types without extra synax.
<lang go>package main
type animal struct {
alive bool
}
type dog struct {
animal
obedienceTrained bool
}
type cat struct {
animal
litterBoxTrained bool
}
type lab struct {
dog
color string
}
type collie struct {
dog
catchesFrisbee bool
}
func main() {
var pet lab
pet.alive = true
pet.obedienceTrained = false
pet.color = "yellow"
}
</lang>
|
Revision as of 07:03, 19 January 2011
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
- This task is about derived types; for implementation inheritance, see Polymorphism.
Inheritance is an operation of type algebra that creates a new type from one or several parent types. The obtained type is called derived type. It inherits some of the properties of its parent types. Usually inherited properties are:
- methods
- components
- parts of the representation
The class of the new type is a subclass of the classes rooted in the parent types. When all (in certain sense) properties of the parents are preserved by the derived type, it is said to be a Liskov subtype. When properties are preserved then the derived type is substitutable for its parents in all contexts. Usually full substitutability is achievable only in some contexts.
Inheritance is
- single, when only one parent is allowed
- multiple, otherwise
Some single inheritance languages usually allow multiple inheritance for certain abstract types, interfaces in particular.
Inheritance can be considered as a relation parent-child. Parent types are sometimes called supertype, the derived ones are subtype. This relation is transitive and reflexive. Types bound by the relation form a wp:Directed_acyclic_graph directed acyclic graph (ignoring reflexivity). With single inheritance it becomes a tree.
Task: Show a tree of types which inherit from each other. The top of the tree should be a class called Animal. The second level should have Dog and Cat. Under Dog should be Lab and Collie. None of the classes need to have any functions, the only thing they need to do is inherit from the specified superclasses (overriding functions should be shown in Polymorphism). The tree should look like this:
Animal /\ / \ / \ Dog Cat /\ / \ / \ Lab Collie
ActionScript
<lang actionscript>public class Animal {
// ...
}</lang> <lang actionscript>public class Cat extends Animal {
// ...
}</lang> <lang actionscript>public class Dog extends Animal {
// ...
}</lang> <lang actionscript>public class Lab extends Dog {
// ...
}</lang> <lang actionscript>public class Collie extends Dog {
// ...
}</lang>
Ada
<lang ada>package Inheritance is
type Animal is tagged private; type Dog is new Animal with private; type Cat is new Animal with private; type Lab is new Dog with private; type Collie is new Dog with private;
private
type Animal is tagged null record; type Dog is new Animal with null record; type Cat is new Animal with null record; type Lab is new Dog with null record; type Collie is new Dog with null record;
end Inheritance;</lang>
Aikido
<lang aikido >class Animal{
//functions go here...
}</lang> <lang aikido >class Dog extends Animal {
//functions go here...
}</lang> <lang aikido >class Cat extends Animal {
//functions go here...
}</lang> <lang aikido >class Lab extends Dog {
//functions go here...
}</lang> <lang aikido >class Collie extends Dog {
//functions go here...
}</lang>
C
- See Inheritance/C
C++
<lang cpp>class Animal {
// ...
};
class Dog: public Animal {
// ...
};
class Lab: public Dog {
// ...
};
class Collie: public Dog {
// ...
};
class Cat: public Animal {
// ...
};</lang>
Common Lisp
Using CLOS classes, we have the following:
<lang lisp>(defclass animal () ()) (defclass dog (animal) ()) (defclass lab (dog) ()) (defclass collie (dog) ()) (defclass cat (animal) ())</lang>
Alternatively, since there is no multiple inheritance, structures could also be used:
<lang lisp>(defstruct animal) (defstruct (dog (:include animal))) (defstruct (lab (:include dog))) (defstruct (collie (:include dog))) (defstruct (cat (:include animal)))</lang>
(Structures are less flexible than CLOS objects but often somewhat more efficiently implemented, due to those restrictions.)
C#
<lang csharp>class Animal { /* ... */ }
class Dog : Animal { /* ... */ }
class Lab : Dog { /* ... */ }
class Collie : Dog { /* ... */ }
class Cat : Animal { /* ... */ }</lang>
D
<lang d>class Animal {
// ...
}
class Dog: Animal {
// ...
}
class Lab: Dog {
// ...
}
class Collie: Dog {
// ...
}
class Cat: Animal {
// ...
}</lang>
Delphi
<lang Delphi>type
Animal = class(TObject) private // private functions/variables public // public functions/variables end;
Dog = class(Animal); Cat = class(Animal); Collie = class(Dog); Lab = class(Dog);</lang>
E
Outside of interactions with the host platform's objects, E does not generally deal in complex type hierarchies; the focus is more on "what guarantees does this object provide", and composition rather than inheritance. However, it is possible to set up a type hierarchy scheme with just a bit of code.
In E, a guard accepts, or coerces, certain objects and rejects others; its range constitutes a type. An auditor examines the implementation of an object and marks it approved; a stamp is an auditor which does no actual checking. Here, we create a guard/stamp pair; the guard accepts every stamped object. The stamp also asks for each supertype's stamp on the objects it audits.
<lang e>def makeType(label, superstamps) {
def stamp { to audit(audition) { for s in superstamps { audition.ask(s) } return true } } def guard { to coerce(specimen, ejector) { if (__auditedBy(stamp, specimen)) { return specimen } else { throw.eject(ejector, `$specimen is not a $label`) } } } return [guard, stamp]
}</lang>
Setting up the task's specified tree:
<lang e>def [Animal, AnimalStamp] := makeType("Animal", [])
def [Cat, CatStamp] := makeType("Cat", [AnimalStamp]) def [Dog, DogStamp] := makeType("Dog", [AnimalStamp])
def [Lab, LabStamp] := makeType("Lab", [DogStamp]) def [Collie, CollieStamp] := makeType("Collie", [DogStamp])</lang>
Some example objects:
<lang e>def fido implements LabStamp {} def tom implements CatStamp {} def brick {} # not an animal</lang>
Testing against the types:
<lang e>? fido :Animal
- value: <fido>
? fido :Cat
- problem: <fido> is not a Cat
? fido :Lab
- value: <fido>
? tom :Animal
- value: <tom>
? tom :Cat
- value: <tom>
? brick :Animal
- problem: <brick> is not a Animal</lang>
Eiffel
<lang eiffel >class
ANIMAL
end</lang> <lang eiffel >class
DOG
inherit
ANIMAL
end</lang> <lang eiffel >class
CAT
inherit
ANIMAL
end</lang> <lang eiffel >class
LAB
inherit
DOG
end</lang> <lang eiffel >class
COLLIE
inherit
DOG
end</lang>
Factor
<lang factor>TUPLE: animal ; TUPLE: dog < animal ; TUPLE: cat < animal ; TUPLE: lab < dog ; TUPLE: collie < dog ;</lang>
Fancy
<lang fancy> def class Animal {
# ...
}
def class Dog : Animal {
# ...
}
def class Cat : Animal {
# ...
}
def class Lab : Dog {
# ...
}
def class Collie : Dog {
# ...
} </lang>
Fortran
OO has been part of the Fortran standard since 2003 but the compilers are still playing catchup. This example builds with the Intel 11.1.069 compiler (free for personal use on linux).
<lang fortran> module anim
type animal end type animal
type, extends(animal) :: dog end type dog
type, extends(animal) :: cat end type cat
type, extends(dog) :: lab end type lab
type, extends(dog) :: collie end type collie
end module anim </lang>
Go
Go eschews most trappings of inheritance, yet it's anonymous field feature allows building one struct type upon another and accessing fields of "embedded" types without extra synax. <lang go>package main
type animal struct {
alive bool
}
type dog struct {
animal obedienceTrained bool
}
type cat struct {
animal litterBoxTrained bool
}
type lab struct {
dog color string
}
type collie struct {
dog catchesFrisbee bool
}
func main() {
var pet lab pet.alive = true pet.obedienceTrained = false pet.color = "yellow"
} </lang>
Groovy
<lang groovy>class Animal{
//contents go here...
}</lang> <lang groovy>class Dog extends Animal{
//contents go here...
}</lang> <lang groovy>class Cat extends Animal{
//contents go here...
}</lang> <lang groovy>class Lab extends Dog{
//contents go here...
}</lang> <lang groovy>class Collie extends Dog{
//contents go here...
}</lang>
Haskell
A type can't inherit properties from other types, but it can belong to any number of type classes, which may themselves be subclasses of other type classes.
<lang haskell>class Animal a class Animal a => Cat a class Animal a => Dog a class Dog a => Lab a class Dog a => Collie a</lang>
HaXe
<lang haxe>class Animal {
// ...
}</lang> <lang haxe>class Cat extends Animal {
// ...
}</lang> <lang haxe>class Dog extends Animal {
// ...
}</lang> <lang haxe>class Lab extends Dog {
// ...
}</lang> <lang haxe>class Collie extends Dog {
// ...
}</lang>
Inform 7
<lang inform7>An animal is a kind of thing. A cat is a kind of animal. A dog is a kind of animal. A collie is a kind of dog. A lab is a kind of dog.</lang>
"Animal" is actually a predefined kind in Inform 7, so its definition here is redundant (but legal).
Io
<lang io>Animal := Object clone Cat := Animal clone Dog := Animal clone Collie := Dog clone Lab := Dog clone</lang>
J
Here is how this would normally be done:
<lang j>coclass 'Animal'</lang> <lang j>coclass 'Dog' coinsert 'Animal'</lang> <lang j>coclass 'Cat' coinsert 'Animal'</lang> <lang j>coclass 'Lab' coinsert 'Dog'</lang> <lang j>coclass 'Collie' coinsert 'Dog'</lang>
coclass
specifies that following definitions will be within the named class, and coinsert
specifies that the current class will inherit from the named classes (or object -- in J the only difference between a class and an object is its name and how you can create them -- this motivates the "co" prefix on operations which manipulate classes and objects).
See http://www.jsoftware.com/help/jforc/modular_code.htm
That said, some operations in J -- including coinsert
-- will create classes if they did not already exist. So the above may be simplified to:
<lang j>coinsert_Dog_ 'Animal' coinsert_Cat_ 'Animal' coinsert_Lab_ 'Dog' coinsert_Collie_ 'Dog'</lang>
That said, note that classes and objects are not "types" in J. Instead, they are components of names. In general, when we deal with objects and classes we deal with references to the underlying representation, and in J the references are names, so a collection of classes and objects, in J, would be a collection of names which refer to classes and objects. In other words, the "type" (to the degree that there is a type) would be best thought of as "name" (or, more mechanically: boxed list of characters).
Java
<lang java>public class Animal{
//functions go here...
}</lang> <lang java>public class Dog extends Animal{
//functions go here...
}</lang> <lang java>public class Cat extends Animal{
//functions go here...
}</lang> <lang java>public class Lab extends Dog{
//functions go here...
}</lang> <lang java>public class Collie extends Dog{
//functions go here...
}</lang>
JavaScript
<lang javascript>function Animal() {
// ...
}</lang>
<lang javascript>function Dog() {
// ...
} Dog.prototype = new Animal();</lang>
<lang javascript>function Cat() {
// ...
} Cat.prototype = new Animal();</lang>
<lang javascript>function Collie() {
// ...
} Collie.prototype = new Dog();</lang>
<lang javascript>function Lab() {
// ...
} Lab.prototype = new Dog();</lang>
<lang javascript>Animal.prototype.speak = function() {print("an animal makes a sound")};
var lab = new Lab(); lab.speak(); // shows "an animal makes a sound"</lang>
Lisaac
<lang Lisaac>Section Header + name := ANIMAL; // ...</lang> <lang Lisaac>Section Header + name := CAT; Section Inherit - parent : ANIMAL := ANIMAL; // ...</lang> <lang Lisaac>Section Header + name := DOG; Section Inherit - parent : ANIMAL := ANIMAL; // ...</lang> <lang Lisaac>Section Header + name := LAB; Section Inherit - parent : DOG := DOG; // ...</lang> <lang Lisaac>Section Header + name := COLLIE; Section Inherit - parent : DOG := DOG; // ...</lang>
Logtalk
There is no "class" keyword in Logtalk; an "object" keyword is used instead (Logtalk objects play the role of classes, meta-classes, instances, or prototypes depending on the relations with other objects). <lang logtalk>:- object(animal).
...
- - end_object.
- - object(dog,
specializes(animal)). ...
- - end_object.
- - object(cat,
specializes(animal)). ...
- - end_object.
- - object(lab,
specializes(dog)). ...
- - end_object.
- - object(collie,
specializes(dog)). ...
- - end_object.</lang>
Objective-C
<lang objc>@interface Animal : NSObject {
// ...
} // ... @end
@interface Dog : Animal {
// ...
} // ... @end
@interface Lab : Dog {
// ...
} // ... @end
@interface Collie : Dog {
// ...
} // ... @end
@interface Cat : Animal {
// ...
} // ... @end</lang>
Objeck
<lang objeck> class Animal { #~ ... ~# }
class Dog from Animal { #~ ... ~# }
class Lab from Dog { #~ ... ~# }
class Collie from Dog { #~ ... ~# }
class Cat from Animal { #~ ... ~# } </lang>
OCaml
<lang ocaml>class animal =
object (self) (*functions go here...*) end</lang>
<lang ocaml>class dog =
object (self) inherit animal (*functions go here...*) end</lang>
<lang ocaml>class cat =
object (self) inherit animal (*functions go here...*) end</lang>
<lang ocaml>class lab =
object (self) inherit dog (*functions go here...*) end</lang>
<lang ocaml>class collie =
object (self) inherit dog (*functions go here...*) end</lang>
Oz
<lang oz>class Animal
%% ...
end
class Dog from Animal
%% ...
end
class Lab from Dog
%% ...
end
class Collie from Dog
%% ...
end
class Cat from Animal
%% ...
end</lang>
Perl
<lang perl>package Animal;
- functions go here...
1;</lang>
<lang perl>package Dog; use Animal; @ISA = qw( Animal );
- functions go here...
1;</lang>
<lang perl>package Cat; use Animal; @ISA = qw( Animal );
- functions go here...
1;</lang>
<lang perl>package Lab; use Dog; @ISA = qw( Dog );
- functions go here...
1;</lang>
<lang perl>package Collie; use Dog; @ISA = qw( Dog );
- functions go here...
1;</lang>
The same using the MooseX::Declare module:
<lang perl>use MooseX::Declare;
class Animal {
# methods go here...
} class Dog extends Animal {
# methods go here...
} class Cat extends Animal {
# methods go here...
} class Lab extends Dog {
# methods go here...
} class Collie extends Dog {
# methods go here...
}</lang>
Perl 6
<lang perl6>class Animal {} class Dog is Animal {} class Cat is Animal {} class Lab is Dog {} class Collie is Dog {}
say ~Collie.^parents; # undefined type object say ~Collie.new.^parents; # instantiated object</lang>
Output:
Dog() Animal() Any() Mu()
Dog() Animal() Any() Mu()
PHP
<lang php>class Animal {
// functions go here...
}
class Dog extends Animal {
// functions go here...
}
class Cat extends Animal {
// functions go here...
}
class Lab extends Dog {
// functions go here...
}
class Collie extends Dog {
// functions go here...
}</lang>
PicoLisp
<lang PicoLisp>(class +Animal)
(class +Dog +Animal)
(class +Cat +Animal)
(class +Lab +Dog)
(class +Collie +Dog)</lang> <lang PicoLisp>: (dep '+Animal) +Animal
+Cat +Dog +Collie +Lab</lang>
PureBasic
Although PureBasic is mostly used for procedural coding it has both the ability to interact with object oriented libraries and code and also the capacity to write it if needed.
<lang PureBasic>Interface Animal
Eat() Sleep()
EndInterface
Interface Cat Extends Animal
ChaseMouse()
EndInterface
Interface Dog Extends Animal
Bark() WagTail()
EndInterface
Interface Lab Extends Dog
Swim()
EndInterface
Interface Collie Extends Dog
HeardSheep()
EndInterface</lang>
Python
Unrevised style classes: <lang python>class Animal:
pass #functions go here...
class Dog(Animal):
pass #functions go here...
class Cat(Animal):
pass #functions go here...
class Lab(Dog):
pass #functions go here...
class Collie(Dog):
pass #functions go here...</lang>
New style classes: <lang python>import time
class Animal(object):
def __init__(self, birth=None, alive=True): self.birth = birth if birth else time.time() self.alive = alive def age(self): return time.time() - self.birth def kill(self): self.alive = False
class Dog(Animal):
def __init__(self, bones_collected=0, **kwargs): self.bone_collected = bones_collected super(Dog, self).__init__(**kwargs)
class Cat(Animal):
max_lives = 9 def __init__(self, lives=max_lives, **kwargs): self.lives = lives super(Cat, self).__init__(**kwargs) def kill(self): if self.lives>0: self.lives -= 1 if self.lives == 0: super(Cat, self).kill() else: raise ValueError return self
class Labrador(Dog):
def __init__(self, guide_dog=False, **kwargs): self.guide_dog=False super(Labrador, self).__init__(**kwargs)
class Collie(Dog):
def __init__(self, sheep_dog=False, **kwargs): self.sheep_dog=False super(Collie, self).__init__(**kwargs)
lassie = Collie() felix = Cat() felix.kill().kill().kill() mr_winkle = Dog() buddy = Labrador() buddy.kill() print "Felix has",felix.lives, "lives, ","Buddy is %salive!"%("" if buddy.alive else "not ")</lang>
Output:
Felix has 6 lives, Buddy is not alive!
R
S3
Inheritance is implemented by setting the object's class attribute with a character vector. <lang R>aCollie <- "woof" class(aCollie) <- c("Collie", "Dog", "Animal")</lang>
S4
Inheritance is implemented by using the 'contains' argument in setClass <lang R>setClass("Animal", representation(), prototype()) setClass("Dog", representation(), prototype(), contains="Animal") setClass("Cat", representation(), prototype(), contains="Animal") setClass("Collie", representation(), prototype(), contains="Dog") setClass("Lab", representation(), prototype(), contains="Dog")</lang>
REBOL
<lang REBOL>REBOL [ Title: "Inheritance" Author: oofoe Date: 2009-12-08 URL: http://rosettacode.org/wiki/Inheritance ]
- REBOL provides subclassing through its prototype mechanism
Animal: make object! [ legs: 4 ]
Dog: make Animal [ says: "Woof!" ] Cat: make Animal [ says: "Meow..." ]
Lab: make Dog [] Collie: make Dog []
- Demonstrate inherited properties
print ["Cat has" Cat/legs "legs."]
print ["Lab says:" Lab/says]</lang>
Output:
Cat has 4 legs. Lab says: Woof!
Ruby
inherited
is a method defined on an instance of a Class
object. It is invoked when a new subclass of the current class is defined (i.e. at the end
statement of a class
definition).
<lang ruby>class Animal
#functions go here... def self.inherited(subclass) puts "new subclass of #{self}: #{subclass}" end
end
class Dog < Animal
#functions go here...
end
class Cat < Animal
#functions go here...
end
class Lab < Dog
#functions go here...
end
class Collie < Dog
#functions go here...
end</lang>
Output
new subclass of Animal: Dog new subclass of Dog: Lab new subclass of Dog: Collie new subclass of Animal: Cat
Scala
Scala has both classes and traits. Classes can only be singly inherited, but both
can inherit a trait multiple times. This inheritance can be declared at the point
of instantiation as well, precluding the need to declare a trait or class for the
sole purpose of combining traits. For the simple inheritance chain of this task,
any (or all) of the class
keywords below can be replaced with trait
<lang scala>class Animal class Dog extends Animal class Cat extends Animal class Lab extends Dog class Collie extends Dog</lang>
Slate
<lang slate>define: #Animal &parents: {Cloneable}. define: #Dog &parents: {Animal}. define: #Cat &parents: {Animal}. define: #Lab &parents: {Dog}. define: #Collie &parents: {Dog}.</lang>
Smalltalk
This is an example of the object serialization format used by many varieties of Smalltalk. Normally the class tree would be defined and navigated via a class browser within a graphical Smalltalk environment. <lang smalltalk>Object subclass: #Animal
instanceVariableNames: ' ' "* space separated list of names *" classVariableNames: ' ' poolDictionaries: ' ' category: ' ' !
"* declare methods here, separated with '!' *" "* !Animal methodsFor: 'a category'! *" "* methodName *" "* method body! !
!Animal subclass: #Dog
"* etc. *" !
!Animal subclass: #Cat
"* etc. *" !
!Dog subclass: #Lab
"* etc. *" !
!Dog subclass: #Collie
"* etc. *" !</lang>
Tcl
or
<lang tcl>package require TclOO oo::class create Animal {
# ...
} oo::class create Dog {
superclass Animal # ...
} oo::class create Cat {
superclass Animal # ...
} oo::class create Collie {
superclass Dog # ...
} oo::class create Lab {
superclass Dog # ...
}</lang>
Vorpal
<lang vorpal>pet = new() cat = new(pet) dog = new(pet) fido = new(dog) felix = new(cat)</lang>
- Programming Tasks
- Basic language learning
- Object oriented
- Type System
- Encyclopedia
- ActionScript
- Ada
- Aikido
- C
- C++
- Common Lisp
- C sharp
- D
- Delphi
- E
- Eiffel
- Factor
- Fancy
- Fortran
- Go
- Groovy
- Haskell
- HaXe
- Inform 7
- Io
- J
- Java
- JavaScript
- Lisaac
- Logtalk
- Objective-C
- Objeck
- OCaml
- Oz
- Perl
- Perl 6
- PHP
- PicoLisp
- PureBasic
- Python
- R
- REBOL
- Ruby
- Scala
- Slate
- Smalltalk
- Tcl
- TclOO
- Vorpal
- ALGOL 68/Omit
- Batch File/Omit
- AWK/Omit
- M4/Omit
- Metafont/Omit
- TI-83 BASIC/Omit
- TI-89 BASIC/Omit
- MIPS Assembly/Omit
- PARI/GP/Omit