Neue Sprachen braucht die Welt (Teil 2)
Kommentare

Haben Sie verglichen?
Im Folgenden sollen C# und Visual Basic den Neulingen F# und IronPython – Letzteres stellvertretend für die dynamischen Sprachen – gegenübergestellt werden. Objektorientiertes Programmieren

Haben Sie verglichen?

Im Folgenden sollen C# und Visual Basic den Neulingen F# und IronPython – Letzteres stellvertretend für die dynamischen Sprachen – gegenübergestellt werden. Objektorientiertes Programmieren ist in all diesen Sprachen möglich, und Sie werden sehen, dass C# in dieser Hinsicht nicht mehr die beste Unterstützung bietet. F# bietet natürlich funktionale Elemente, deren Emulation in den anderen Sprachen oft gewisse Tricks erfordert. Im dynamischen Bereich lässt sich (Iron)Python natürlich nichts vormachen, und dies bietet für gewisse Anwendungsfälle große Vorteile. Objektorientierte Programmierung ist in C# natürlich der Ansatz der Wahl. In dieser Sprache, wie auch in Visual Basic, gibt es keinen Code außerhalb von Klassen. Die Listings 1 und 2 zeigen die Implementation einer minimalen Klassenhierarchie mit einem Interface in diesen beiden Sprachen, sowie den Umgang mit der Klasse und dem Interface.

public interface IEat {
  void Eat( );
}

public abstract class Animal {
  public abstract void Sleep( );
}

public class Dog : Animal, IEat {
  public override void Sleep( ) {
    Console.WriteLine("C# dog sleeping");
  }

  // Interface method
  public void Eat( ) {
    Console.WriteLine("C# dog eating");
  }
}

...

var dog = new Dog( );
dog.Sleep( );
(dog as IEat).Eat( );  

Listing 1

Public Interface IEat
  Sub Eat()
End Interface

Public MustInherit Class Animal
  Public MustOverride Sub Sleep()
End Class

Public Class Dog
  Inherits Animal
  Implements IEat

  Public Overrides Sub Sleep()
    Console.WriteLine("VB dog sleeping")
  End Sub

  ' Interface method
  Public Sub Eat() Implements IEat.Eat
    Console.WriteLine("VB dog eating")
  End Sub
End Class

...

Dim dog As Dog = New Dog()
dog.Sleep()
DirectCast(dog, IEat).Eat()  

Listing 2

Bei der Entwicklung von F# wurde besonders auf die Kompatibilität mit der objektorientierten Welt von .NET Wert gelegt, und dieses Beispiel lässt sich daher sehr einfach umsetzen, wie Listing 3 zeigt. Trotzdem gibt es in F# einige Besonderheiten:

  • Für abstrakte Klassen gibt es kein besonderes Schlüsselwort, weshalb stattdessen ein Attribut eingesetzt wird (die Klammern [<...>] werden in F# für .NET-Attribute verwendet).
  • Es gibt keine protected Sichtbarkeit in F#, was für dieses Beispiel jedoch irrelevant ist.
  • Interfaces sind immer (im C#-Sinn) explizit implementiert. Im C#-Beispiel selbst wurde hingegen implizite Implementation gewählt.
type IEat = 
  abstract Eat : unit -> unit
    
[]
type Animal() =
  abstract Sleep : unit -> unit

type Dog() = 
  inherit Animal()
  default x.Sleep() = printfn "F# dog sleeping"
    
  interface IEat with
    member x.Eat() = printfn "F# dog eating"

let dog = Dog()
dog.Sleep()
(dog :> IEat).Eat()  

Listing 3

In IronPython schließlich zeigen sich bei der Umsetzung dieses Beispiels schon einige Besonderheiten: Weder abstrakte Klassen noch „echte“ Interfaces im Sinne von .NET werden in dieser Sprache unterstützt. Listing 4 zeigt, wie eine vergleichbare Klassenhierarchie implementiert werden kann. In der Klasse Animal wird der Begriff abstract benutzt. Dabei handelt es sich aber nicht um ein Schlüsselwort der Sprache, sondern stattdessen um ein fehlendes Element. Mit diesem Trick wird bewirkt, dass beim Aufruf der Funktion sleep ein Laufzeitfehler ausgelöst wird. Dies ist nicht grundsätzlich unüblich in dynamischen Sprachen – der Compiler kann nicht endgültig beurteilen, ob der Identifier abstract zur Laufzeit eine Bedeutung haben wird oder nicht.

Protokolle statt Schnittstellen

p>Interfaces gibt es in (Iron)Python nicht. Zu ähnlichen Zwecken werden oft so genannte Protokolle eingesetzt. Dabei handelt es sich schlicht um Definitionen der Form: „Wenn eine Klasse die Funktionen X und Y implementiert, mit kompatiblen Signaturen, dann gehorcht sie dem Protokoll XY“. Dies ist eine Auswirkung des in Python verwendeten Duck Typing, benannt nach dem Prinzip „Wenn es aussieht wie eine Ente und quakt wie eine Ente, dann ist es (vermutlich) eine Ente“. Natürlich dienen Interfaces außer den technischen Aspekten auch anderen Zwecken, wie etwa der vereinfachten Dokumentation gewisser Verhaltensweisen oder der intuitiven Zugänglichkeit zu APIs. In Python werden manchmal bestimmte Namenskonventionen („__eat__“ anstelle von „eat“) oder Hilfsfunktionen verwendet, und es gibt mehrere von der Sprache selbst unabhängige Librarys, die auf der Basis von Duck Typing eine formellere Interfacesyntax ermöglichen.

class Animal:
  def sleep(self): abstract

class Dog(Animal):
  def sleep(self):
    print "Python dog sleeping"

  def eat(self):
    print "Python dog eating" 

dog = Dog()
dog.sleep()
dog.eat()  

Listing 4

Speziell in F# gibt es einige objektorientierte Features, die C# und Visual Basic nicht zu bieten haben. Drei Beispiele finden Sie in Listing 5: Instantiierungsausdrücke, Komposition und „discriminated unions“.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -