Aus Raspberry Pi Geek 07-08/2020

Typen, Module, Plots und Makros in der Programmiersprache Julia (Seite 2)

Typhierarchien

Julia bietet einen minimalistischen Vererbungsmechanismus, den Listing 3 skizziert. Zeile 4 definiert den abstrakten Datentyp Audio. Ein solcher abstrakter Datentyp kann keine Attribute besitzen, darf aber nur von abstrakten Typen erben. Es ist also nicht möglich, gemeinsame Eigenschaften verschiedener Typen über Vererbung zu organisieren.

Listing 3

# file inherit.jl
import Base.show
abstract type Audio end
struct Song <: Audio
  name::String
end
struct Audiobook <: Audio
  name::String
end
play(s::Song) = "lala"
play(s::Audiobook) = "blabla"
show(io::IO, a::Audio) = print(io, a.name)

Die Typen Song und Audiobook erben von Audio. Die Zeilen 15 und 16 definieren verschiedene Methoden play() für Argumente vom Typ Song und Audiobook.

Die Methode show() kommt immer dann zum Zug, wenn die String-Darstellung eines Objektes gefragt ist, zum Beispiel bei einem Aufruf von println(). Zeile 17 definiert show() auf Argumente des Typs Audio für eine maßgeschneiderte String-Ausgabe. Ähnlich wie bei der Multiplikation erfordert das den Import von Base.show().

Das Beispiel zeigt, dass die Vererbung für Julia lediglich dazu dient, unterschiedliche Typen bei Bedarf gemeinsam zu behandeln: play() ist auf die konkreten Typen hin implementiert, show() auf den abstrakten Typ Audio, der Song und Audiobook zusammenfasst.

Listing 4 demonstriert wiederum die Anwendung im interaktiven Modus. Sie sehen, dass bereits die Ausgabe nach dem Konstruktoraufruf die spezifische show-Methode von Audio aufruft. methods(play) informiert, dass es zwei play-Methoden gibt und zeigt die entsprechenden Dateipfade an.

Listing 4

> include("inherit.jl");
> a = Audiobook("Plato: Menon")
Plato: Menon
> s = Song("ABBA: S.O.S")
ABBA: S.O.S
> methods(play)
# 2 methods for generic function "play":
[1] play(s::Audiobook) in Main at ...
[2] play(s::Song) in Main at ...
> play(a)
"blabla"
> play(s)
"lala"
> [a, s]
2-element Array{Audio,1}:
 Plato: Menon
 ABBA: S.O.S

Fasst man Songs und Audiobooks mit [a, s] in einem Array zusammen, erkennt Julia den spezifischsten gemeinsamen Supertyp dieser Objekte, nämlich Audio. Bei Objekten, die sich nicht in dieser Form auf einen Nenner bringen lassen, wäre der Typ des Arrays Any.

Möchten Sie mehr über Typen in Julia erfahren, werden Sie in der offiziellen Dokumentation fündig [3]. Zu den für fortgeschrittene Anwender wichtigen, hier ausgelassenen Themen zählen parametrische Typen, primitive Typen und Unions.

Module und Namensräume

Wie jede halbwegs moderne Programmiersprache modularisiert auch Julia Programme und Namensräume über das Schlüsselwort module. Listing 5 definiert das Modul Adder. Es enthält die beiden Methoden add_sugar() und add_salt().

Listing 5

# file adder.jl
module Adder
export add_sugar
add_sugar(x) = string(x)*" + sugar"
add_salt(x) = string(x)*" + salt"
end

Diese wandeln das übergebene Argument in einen String um und fügen "+ sugar" beziehungsweise "+ salt" hinzu. Die String-Verknüpfung läuft per Asterisk (*). Die Bedeutung der export-Anweisung verdeutlicht Listing 6.

Listing 6

> include("adder.jl")
Main.Adder
> Adder.add_sugar("tea")
"tea + sugar"
> Adder.add_sugar(7)
"7 + sugar"
> Adder.add_salt("fries")
"fries + salt"
> using .Adder
> add_sugar("coffee")
"coffee + sugar"
> add_salt("soup")
ERROR: UndefVarError: add_salt not defined

Wie gehabt fügen wir die Datei adder.jl per include() ein, was es erlaubt, über den Namen des Moduls auf dessen Funktionen zuzugreifen: Adder.add_sugar(). Knapper schreibt es sich, wenn Sie das Modul per using .Adder einbinden, äquivalent mit dem Ausdruck using Main.Adder.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 8 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
RASPBERRY PI GEEK KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Raspberry Pi Geek bei Google Play Readly Logo
Nach oben