Inheritance/Multiple

From Rosetta Code
Revision as of 18:17, 21 March 2011 by rosettacode>Jofur (→‎{{header|Pop11}}: Added PureBasic)
Task
Inheritance/Multiple
You are encouraged to solve this task according to the task description, using any language you may know.

Multiple inheritance allows to specify that one class is a subclass of several other classes. Some languages allow multiple inheritance for arbitrary classes, others restrict it to interfaces, some don't allow it at all.

Write two classes (or interfaces) Camera and MobilePhone, then write a class CameraPhone which is both a Camera and a MobilePhone.

There is no need to implement any functions for those classes.

Ada

Ada 2005 has added interfaces, allowing a limited form of multiple inheritance. <lang ada>package Multiple_Interfaces is

  type Camera is tagged null record;
  type Mobile_Phone is limited Interface;
  type Camera_Phone is new Camera and Mobile_Phone with null record;

end Multiple_Interfaces;</lang>

Aikido

Aikido does not support multiple inheritance, but does allow multiple implementation of interfaces. <lang aikido> interface Camera { }

interface Mobile_Phone { }

class Camera_Phone implements Camera, Mobile_Phone { }

</lang>

C++

<lang cpp>class Camera {

 // ...

};

class MobilePhone {

 // ...

};

class CameraPhone:

 public Camera,
 public MobilePhone

{

 // ...

};</lang>

C#

In C# you may inherit from only one class, but you can inherit from multiple interfaces. Also, in C# it is standard practice to start all interface names with a capital 'I' so I have altered the name of the interface. In the example we inherit from a class and an interface.

<lang csharp>interface ICamera {

   // ...

}

class MobilePhone {

   // ...

}

class CameraPhone: ICamera, MobilePhone {

   // ...

}</lang>

Common Lisp

<lang lisp>(defclass camera () ()) (defclass mobile-phone () ()) (defclass camera-phone (camera mobile-phone) ())</lang>

D

D doesn't allow multiple inheritance, but you can inherit after multiple interfaces.

<lang d>interface Camera {

   // member function prototypes and static methods

}

interface MobilePhone {

   // member function prototypes and static methods

}

class CameraPhone: Camera, MobilePhone {

   // member function implementations for Camera,
   //   MobilePhone, and CameraPhone

}</lang> D also supports template mixins and alias this (multiple alias this are planned) that allows various forms of static composition.

E

E does not have multiple inheritance as a built-in feature. In fact, E only has inheritance at all as a light syntactic sugar over delegation (message forwarding). However, using that facility it is possible to implement multiple inheritance.

This is a quick simple implementation of multiple inheritance. It simply searches (depth-first and inefficiently) the inheritance tree for a method; it does not do anything about diamond inheritance. These shortcomings could be fixed if more powerful multiple inheritance were needed.

<lang e>def minherit(self, supers) {

   def forwarder match [verb, args] {
       escape __return {
           if (verb == "__respondsTo") {
               def [verb, arity] := args
               for super ? (super.__respondsTo(verb, arity)) in supers {
                   return true
               }
               return false
           } else if (verb == "__getAllegedType") {
               # XXX not a complete implementation
               return supers[0].__getAllegedType()
           } else {
               def arity := args.size()
               for super ? (super.__respondsTo(verb, arity)) in supers {
                   return E.call(super, verb, args)
               }
               throw(`No parent of $self responds to $verb/$arity`)
           }
       }
   }
   return forwarder

}</lang>

The task example:

<lang e>def makeCamera(self) {

   return def camera extends minherit(self, []) {
       to takesPictures() { return true }
   }

}

def makeMobilePhone(self) {

   return def mobilePhone extends minherit(self, []) {
       to makesCalls() { return true }
       to internalMemory() { return 64*1024 }
   }

}

def makeCameraPhone(self) {

   return def cameraPhone extends minherit(self, [
       makeCamera(self),
       makeMobilePhone(self),
   ]) {
       to internalMemory() {
           return super.internalMemory() + 32 * 1024**2
       }
   }

}</lang >

And testing that it works as intended:

<lang e> ? def p := makeCameraPhone(p) > [p.takesPictures(), p.makesCalls(), p.internalMemory()]

  1. value: [true, true, 33619968]</lang>

Eiffel

<lang eiffel >class

   CAMERA

end</lang> <lang eiffel >class

   MOBILE_PHONE

end</lang> <lang eiffel >class

   CAMERA_PHONE

inherit

   CAMERA
   MOBILE_PHONE

end</lang>

Fantom

Fantom only permits inheritance from one parent class. However, Fantom supports 'mixins': a mixin is a collection of implemented methods to be added to the child class. Any number of mixins can be added to any given child class. It is an error for method names to conflict.

<lang fantom> // a regular class class Camera {

 Str cameraMsg ()
 {
   "camera"
 }

}

// a mixin can only contain methods mixin MobilePhone {

 Str mobileMsg ()
 {
   "mobile phone"
 }

}

// class inherits from Camera, and mixes in the methods from MobilePhone class CameraPhone : Camera, MobilePhone { }

class Main {

 public static Void main ()
 {
   cp := CameraPhone ()
   echo (cp.cameraMsg)
   echo (cp.mobileMsg)
 }

} </lang>

F#

A class can only inherit from one other class, but it can implement any number of interfaces.

<lang fsharp>type Picture = System.Drawing.Bitmap // (a type synonym)

// an interface type type Camera =

 abstract takePicture : unit -> Picture

// a class with an abstract method with a default implementation // (usually called a virtual method) type MobilePhone() =

 abstract makeCall : int[] -> unit
 default x.makeCall(number) = () // empty impl

// a class that inherits from another class and implements an interface type CameraPhone() =

 inherit MobilePhone()
 interface Camera with
   member x.takePicture() = new Picture(10, 10)</lang>

Go

Go interfaces can be composed, per task description. Types implement interfaces simply by implementing functions. The type does not explicitly declare the interfaces it implements. <lang go>package main

import "fmt"

type camera interface {

   photo()

}

type mobilePhone interface {

   call()

}

type cameraPhone interface {

   camera
   mobilePhone

}

type htc int

func (htc) photo() {

   fmt.Println("snap")

}

func (htc) call() {

   fmt.Println("omg!")

}

func main() {

   var i cameraPhone = new(htc)
   i.photo()
   i.call()

} </lang> Output:

snap
omg!

Haskell

<lang haskell>class Camera a class MobilePhone a class (Camera a, MobilePhone a) => CameraPhone a</lang>

Icon and Unicon

Icon does not support classes or inheritance. An intermediate language called Idol was developed as proof of concept for extending Icon. This became one of the major addons contributing to Unicon.

<lang unicon> class Camera (instanceVars)

   # methods...
   # initializer...

end

class Phone (instanceVars)

   # methods...
   # initializer...

end

class CameraPhone : Camera, Phone (instanceVars)

   # methods...
   # initialiser...

end</lang>

Ioke

<lang ioke>Camera = Origin mimic MobilePhone = Origin mimic CameraPhone = Camera mimic mimic!(MobilePhone)</lang>

J

<lang j>coclass 'Camera'

create=: verb define

 NB. creation-specifics for a camera go here

)

destroy=: codestroy

NB. additional camera methods go here

coclass 'MobilePhone'

create=: verb define

 NB. creation-specifics for a mobile phone go here

)

destroy=: codestroy

NB. additional phone methods go here

coclass 'CameraPhone' coinsert 'Camera MobilePhone'

create=: verb define

 create_Camera_ f. y
 create_MobilePhone_ f. y
 NB. creation details specific to a camera phone go here

)

destroy=: codestroy

NB. additional camera-phone methods go here</lang> The adverb Fix (f.) is needed as shown so the superclass constructors get executed in the object, not in the superclass.

Java

Java does not allow multiple inheritance, but you can "implement" multiple interfaces. All methods in interfaces are abstract (they don't have an implementation). When you implement an interface you need to implement the specified methods. <lang java>public interface Camera{

  //functions here with no definition...
  //ex:
  //public void takePicture();

}</lang> <lang java>public interface MobilePhone{

  //functions here with no definition...
  //ex:
  //public void makeCall();

}</lang> <lang java>public class CameraPhone implements Camera, MobilePhone{

  //functions here...

}</lang>

Logtalk

Logtalk supports multiple inheritance. 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(camera,

   ...).
   ...
- end_object.</lang>

<lang logtalk>:- object(mobile_phone,

   ...).
   ...
- end_object.</lang>

<lang logtalk>:- object(camera_phone,

   specializes(camera, mobile_phone),
   ...).
   ...
- end_object.</lang>

Objective-C

Like Java, Objective-C does not allow multiple inheritance, but a class can "conform to" multiple protocols. All methods in protocols are abstract (they don't have an implementation). When you conform to a protocol you need to implement the specified methods. <lang objc>@protocol Camera //methods here with no definition... //ex: -(void)takePicture; @end</lang> <lang objc>@protocol MobilePhone //methods here with no definition... //ex: -(void)makeCall; @end</lang> <lang objc>@interface CameraPhone : NSObject <Camera, MobilePhone> {

  //variable declarations here

}

//method declarations go here //methods declared in protocol(s) are implicitly included and there is no need to declare them again @end

@implementation CameraPhone //method implementations go here, including for takePicture and makeCall @end</lang>

OCaml

<lang ocaml>class camera =

 object (self)
   (*functions go here...*)
 end</lang>

<lang ocaml>class mobile_phone =

 object (self)
   (*functions go here...*)
 end</lang>

<lang ocaml>class camera_phone =

 object (self)
   inherit camera
   inherit mobile_phone
   (*functions go here...*)
 end</lang>

Oz

<lang oz>class Camera end

class MobilePhone end

class CameraPhone from Camera MobilePhone end</lang>

Perl

<lang perl>package Camera;

  1. functions go here...

1;</lang>

<lang perl>package MobilePhone;

  1. functions go here...

1;</lang>

<lang perl>package CameraPhone; use Camera; use MobilePhone; @ISA = qw( Camera MobilePhone );

  1. functions go here...

1;</lang>

or

<lang perl>package CameraPhone; use base qw/Camera MobilePhone/;

  1. functions go here...</lang>

The same using the MooseX::Declare extention: <lang perl>use MooseX::Declare;

class Camera {

   # methods ...

} class MobilePhone {

   # methods ...

} class CameraPhone extends(Camera, MobilePhone) {

   # methods ...

}</lang>

Perl 6

Works with: Rakudo Star version 2010.07

<lang perl6>class Camera {} class MobilePhone {} class CameraPhone is Camera is MobilePhone {}

say ~CameraPhone.^parents; # undefined type object say ~CameraPhone.new.^parents; # instantiated object</lang>

Output:

Camera() MobilePhone() Any() Mu()
Camera() MobilePhone() Any() Mu()

PicoLisp

<lang PicoLisp>(class +Camera)

(class +MobilePhone)

(class +CameraPhone +Camera +MobilePhone)</lang>

Pop11

<lang pop11>;;; load object support lib objectclass;

define :class Camera;

  ;;; slots go here

enddefine;

define :class MobilePhone;

  ;;; slots go here

enddefine;

define :class CameraPhone is Camera, MobilePhone;

  ;;; extra slots go here

enddefine;

methods go here</lang>

PureBasic

Using the open-source precompiler PureOOP. <lang PureBasic>Class Camera EndClass

Class Mobil EndClass

Class CameraMobile Extends Camera Extends Mobil EndClass</lang>

Python

<lang python>class Camera:

 pass #functions go here...</lang>

<lang python>class MobilePhone:

 pass #functions go here...</lang>

<lang python>class CameraPhone(Camera, MobilePhone):

 pass #functions go here...</lang>

Ruby

Ruby does not have multiple inheritance, but you can mix modules into classes: <lang ruby>module Camera

 # define methods here

end class MobilePhone

 # define methods here

end class CameraPhone < MobilePhone

 include Camera
 # define methods here

end</lang>

Slate

<lang slate>define: #Camera. define: #MobilePhone. define: #CameraPhone &parents: {Camera. MobilePhone}.</lang>

Tcl

Works with: Tcl version 8.6

or

Library: TclOO

<lang tcl>package require TclOO

oo::class create Camera oo::class create MobilePhone oo::class create CameraPhone {

   superclass Camera MobilePhone

}</lang>