Moniperintään liittyy useita ongelmia, joiden vuoksi esimerkiksi Java ja monet muut ohjelmointikielet eivät tue sitä. Javassa käytetään interfaceja simuloimaan moniperintää. Interfaceissa ei voi kuitenkaan olla ohjelmakoodia, joten ohjelmoijan pitää itse toteuttaa kaikki interfaceen liittyvät toiminnot omassa luokassaan. Seurauksena on sitä ikävää turhaa bloattia, josta Java-ohjelmat ovat tunnettuja.

Rubyn mixinit

Rubyssa moniperintä on ratkaistu mixineillä, jotka ovat oikein kaunis ja yksinkertainen tapa lisätä valmiita toimintoja omiin luokkiin. Tämä on kätevää pitkälti sen vuoksi, että kielessä on dynaaminen tyypitys. Mixin on käytännössä valmiita apumetodeita sisältävä moduuli. Nämä apumetodit voi lisätä "lennossa" omaan olioonsa extend-kutsulla:
module Sayable
  def say
    puts @message
  end
end

class Hello
  def initialize
    @message = 'Hello, World'
  end
end

hello = Hello.new
hello.extend Sayable
hello.say

Jos apumetodit haluaa lisätä pysyvästi mukaan omaan luokkaansa, sen voi tehdä luokkamäärittelyssä include-kutsulla:

class Hello
  def initialize
    @message = 'Hello, World'
  end
  include Sayable
end

Pythonin mixinit

Pythonissa on moniperintä, mutta sen käyttö saattaa olla tarpeettoman hankalaa omissa projekteissa. Esimerkiksi konstruktorien kutsuminen oikealla tavalla on hieman epäintuitiivista ja menee heti rikki, jos hierarkian yksikin luokka jättää kutsumatta super-konstruktoria.

Monessa tapauksessa voikin olla järkevämpää simuloida mixinejä käyttämällä moniperintää pelkkien apumetodien määrittelyyn. Tässä lähestymistavassa mixin-luokassa ei ole konstruktoria eikä omia instanssimuutujia. Se vain olettaa, että mixiniä käyttävässä luokassa tietyt instanssimuuttujat on jo määritelty:

class Sayable(object):
    def say(self):
        print(self.message)

class Hello(Sayable):
    def __init__(self):
        self.message = 'Hello, World'

hello = Hello()
hello.say()

Oma Hello-luokka voi periytyä jostain muusta luokasta. Silloin ohjelmoijan pitää huomioida super-konstruktorin kutsuminen oman koodinsa osalta, mutta mixin-luokista ei tarvitse välittää:

class Sayable(object):
    def say(self):
        print(self.message)

class ExampleBase(object):
    def __init__(self):
        pass

class Hello(ExampleBase, Sayable):
    def __init__(self):
        super(Hello, self).__init__()
        self.message = 'Hello, World'

hello = Hello()
hello.say()

Tämä malli toimii parhaiten, jos isäntäluokka on aina ensimmäisenä perimäluettelossa, ja mixin-luokat tulevat sen jälkeen. Pythonin MRO (method resolution order) kulkee nimittäin vasemmalta oikealle, ja super-kutsut kohdistuvat ensimmäisenä vasemmanpuoleisimpaan isäntäluokkaan.

Published 23.9.2009