About
fv_2007
Agile innovative developer with deep insight into lots of platforms, technologies and protocols. Absolute “early adopter” in Web 2.0 technologies and more. Large professional network and eagerly talking about architecture, strategy, design patterns, restful ressources, object-oriented thinking and modeling languages such as PML. Special interest in programminglanguages constructs, knowledge on languages like Smalltalk, Erlang, Java, Clojure, Scala, Ruby... read more
Comments
Language

Multiple inheritance November 26, 2007 04:52 over 4 years ago

Java’s model er multiple interfaces og single implementation. Det betyder at en klasse kan arve fra netop en superklasse og implementere flere interfaces. Det er en meget almindelig model. Hvis dine objekter skal være persistente og samtidige være sikre kan dette opnås gennem at implementere to interfaces. Det er denne form for multiple inheritance som Java og C# har adopteret.

Men der findes andre former for multiple inheritance, men man kan også bruge delegation. Normalt arve man fra flere klasser for at sammensmelte forskellige egenskaber. Dog bør man kun bruger multiple arv når det gælder simple konstruktioner.

Mange påstår korrekt at multiple arv ikke behøves fordi alt kan gøres på andre måder. Man behøver slet ikke arv i det hele taget. Man behøver faktisk ikke klasse, man kan jo bare allokere pointer og data strukturer. Det er nemt at argumentere med eller imod disse sprog konstruktionsmæssige fremgangsmåder. Så hvorfor bruger vi de egenskaber som er bygget ind i de forskellige sprog?

Jeg bruger alle de facetter som sproget giver mig mulighed for.

Multiple inheritance er understøttet i sprog som fx: Eiffel, C++, Python og Perl men Java har ikke mulighed for multiple arv. Java er til dels baseret på C++ og på et tidspunkt skulle man beslutte hvilken af de ting som ofte blev brugt uhensigtsmæssigt og som ikke skulle med i Java. En af de ting som ikke kom med var multiple arv.

Java er tænkt som et enkelt, typestærkt og specielt sikkert sprog, hvori man kan producere forretningskode som kan eksekveres på en sikker platform. Java er et multi propose sprog som kan anvendes til alle typer af opgaver og af alle typer af programmører.

I mange år har der forgået en diskussion bland C++ tilhængere om den største svaghed i Java er manglen på multiple nedarving. Jeg vil argumentere at objektorienteret udvikling ikke kræver multiple arv overhoved. Ydermere har jeg lade mig fortælle fra C++ venner at ingen kunne finde ud af den kompleksitet som følger med multiple arv. Fx metode navne sammenfald, retur type inkonsistens, kalde sekvens, Interface collision og the diamond problem osv.

I C++ benyttes virtual inheritance metoden til at eliminere mange af de problemer som opstår. Lisp lader blot den mest specialiserede metode vinde eller lader det være op til programmøren. Eiffel lader programmøren omdøbe metode navne eksplicit.

Klassisk eksempel. VeryBadVampire har for eksempel problemer med menace(); metoden.

interface Monster {
  void menace();
}

interface DangerousMonster extends Monster {
  void destroy();
}

interface Lethal {
  public void menace();
  void kill();
}

class DragonZilla implements DangerousMonster {
  public void menace() {}
  public void destroy() {}
}

interface Vampire extends DangerousMonster, Lethal {
  void drinkBlood();
}

class VeryBadVampire implements Vampire {
  public void menace() {}
  public void destroy() {}
  public void kill() {}
  public void drinkBlood() {}
}

public class HorrorShow {

    static void u(Monster b) { b.menace(); }
    static void v(DangerousMonster d) { d.menace(); d.destroy(); }
    static void w(Lethal l) { l.kill(); }

  public static void main(String ... args) {
    DangerousMonster barney = new DragonZilla();
    u(barney);
    v(barney);
    Vampire vlad = new VeryBadVampire();
    u(vlad);
    v(vlad);
    w(vlad);
  }
}

Det var the diamond problem!

Ruby’s bud er et enkelt men kraftfuldt kompromis mellem single inheritance og multiple inheritance. En Ruby klasse kan kun have én direkte superklasse og er dermed single inheritance sprog. Men Ruby kan inkluder metoder fra en til mange mixins. Ligesom Smalltalk.

En mixin er som en partial(del klasse definition) og kan nemt ses som et interface med implementering. Det giver kontrolleret multiple inheritance men uden nogen af de ulemper som normalt følger med. PS. Normalt vil man aldrig bygge det op sådan i Ruby, dette er kun for eksemplet!

module Monster
  def menace 
    "Monster menace"
  end
end

module DangerousMonster 
  include Monster
end

module Lethal
  def menace 
    "Lethal menace"
  end
end

module Vampire
  include DangerousMonster
  include Lethal
end 

class VeryBadVampire
  include Vampire
end

d = VeryBadVampire.new

p d.menace # Monster menace

Hvordan kan man vide om modulet Vampire bruger den ene eller den anden menace metode?


By Frank Vilhelmsen - 1 tag: architecture - Add comment