Android-Programmierung mit Scala

Merkmale anstatt Vererbung

Eine der bedeutendsten Unterschiede zwischen Scala und Java ist der Bereich der objektorientierten Vererbung. Wie allseits bekannt, unterstützt Java ausschließlich Einfachvererbung von abstrakten und konkreten Klassen. Scala-Klassen können zwar Java-Interfaces implementieren und von Java-Klassen ableiten, prinzipiell wird jedoch mit dem Konzept der Traits (dt. Merkmal, Eigenschaft) gearbeitet. Ein Trait kann jeder beliebige Implementierungsgrad im Spektrum zwischen einem Interface und einer konkreter Klasse sein. Im Unterschied zu Java kann jedoch eine Scala-Klasse von mehreren Traits ableiten, auch wenn diese konkrete Methodenimplementierungen beinhalten. So leitet beispielsweise der TypedActivity Trait aus dem vorhergehenden Beispiel ebenfalls von der Basisklasse android.app.Activity ab. Obwohl die LoginActivity selbst von der gleichen Basisklasse ableitet, kann der Scala Compiler durch sog. Linearisierung den Vererbungspfad in eine einzige Dimension überführen. An dieser Stelle macht es durchaus Sinn, einen Blick in die vom Scala Android Plug-in generierte TR.scala-Datei zu werfen, was wir bis dato vermieden haben (Listing 9).

Listing 9
trait TypedActivityHolder {
  def activity: Activity
  def findView[T](tr: TypedResource[T]) =
                                 activity.findViewById(tr.id).asInstanceOf[T]
}

trait TypedActivity extends Activity with TypedActivityHolder { 
  def activity = this
}

Traits sind besonders für Projekte interessant, die sich innerhalb eines Frameworks bewegen müssen. In ihnen besteht oft die Ausgangslage, von Frameworkklassen ableiten zu müssen. Somit besteht in Java die Schwierigkeit für den Entwickler, keine gemeinsamen Basistypen einführen zu können. Das hat in der Praxis das Resultat, mit einer Menge an Utility-Klassen als Ansammlung von einzelnen Funktionen/Prozeduren zu enden, was wiederum gegen objektorientierte Dogmen verstößt.

Sehen wir uns nun Traits an einem trivialen Beispiel an: die Implementierung eines Option Menus, das in gewissen Activities der Anwendung wiederverwendet werden soll. Nun besteht das Problem, dass bei unterschiedlichen Activity-Basisklassen kein gemeinsamer projektspezifischer Basistyp zur Definition von genereller Funktionalität – wie die Definition eines Option Menu – implementiert werden kann. Man ist auf die Einführung einer OptionsMenuUtility-Klasse oder ähnliches angewiesen, die dann wiederum für die Implementierung der *options*-Methoden aus der Activity-Basisklasse herangezogen wird.

Listing 10
trait OptionsMenu extends Activity {

  override def onCreateOptionsMenu(menu: Menu) : Boolean = {
    menu.add(0, 1, 1, "Some Menu Item")
    return true
  }

  override def onOptionsItemSelected(item: MenuItem) : Boolean = {
    item.getItemId match  {
      case 1 => true
      case _ => throw new IllegalArgumentException("item is not known!")
    }
  }
}

Der in Listing 10 gezeigte Trait zeigt eine exemplarische Implementierung des OptionsMenu Traits. Dieser Trait kann nun in allen indirekt oder direkt von android.app.Activity ableitenden Implementierungen über Vererbung mit dem with-Schlüsselwort eingebunden werden (Listing 11). Besonders zu beachten ist die Möglichkeit, den Trait auf indirekte android.app.Activity-Klassen anzuwenden, wie es mit der android.app.ListActivity der Fall ist.

Im Übrigen ist in der Methode onOptionsItemSelected ein weiteres Sprachfeature von Scala zu sehen: Pattern Matching. Scala bietet einen mächtigen Pattern-Matching-Mechanismus, der an Erlang erinnert. Für eine Einführung in diese Thematik sei an dieser Stelle auf die entsprechende Seite in der Scala-Dokumentation verwiesen [9].

Listing 11
class LoginActivity extends Activity with TypedActivity with OptionsMenu {
// ...
}

class SomeListActivity extends ListActivity with OptionsMenu {
// ...
}
Zusammenfassung

Dieser Artikel sollte einen kleinen Einblick in die Android-Entwicklung mit Scala gegeben haben. Die Verwendung von Scala ist jedoch längst nicht auf die in diesem Artikel gezeigten Features beschränkt. Das kann der Leser bei einem Blick in die Scala-Dokumentation [10] unschwer feststellen. Vor allem Operatorenüberladung, fallbasierte Klassen und die Scala-Klassenbibliothek beinhalten weitere hochinteressante Konzepte. Obwohl Scala nicht von Google und der Open Handset Alliance als Programmierumgebung für die Android-Entwicklung unterstützt wird, haben Entwickler mit dem Simple Build Tool (SBT) und dem zugehörigen Scala Android Plugin bereits ein gutes Buildmanagement-Tool zur Verfügung, mit dem sich der Build-Vorgang weitestgehend automatisieren lässt.

Der Einsatz von Scala in produktiven Android-Applikationen ist jedoch schon aus möglichen Kompatibilitätsbrüchen mit der Dalvik VM und dem Dex Compiler in zukünftigen Android-Versionen fraglich. Auch die von Haus aus fehlende Unterstützung von Scala in den Android-Projektfacetten verbreiteter IDEs (Eclipse, IntelliJ) kann als gewichtiger Nachteile gesehen werden. Können diese Nachteile in Kauf genommen werden, kann mit Scala statisch typisierter, objektorientierter Code geschrieben werden, der in dieser Form unter Verwendung von Java nur über eine Vielzahl von außerordentlichen Verrenkungen möglich wäre.

Es bleibt spannend, ob sich neben Java noch weitere Sprachen in der Android-Entwicklung etablieren und ob sie auch von offizieller Seite unterstützt werden. Dies wäre einer Professionalisierung der Softwareentwicklung unter Android zuträglich, würde die Programmqualität der erstellten Komponenten erhöhen und die (Entwickler-)Welt ein kleines Stück verbessern.

Andre Steingress ist als freiberuflicher Softwareentwickler in Linz (Österreich) tätig. In seinen Projekten arbeitet er an Android-Applikationen für Telekommunikationsanbieter und JEE/Grails basierten Backends. In seiner Freizeit ist er Projektleiter von GContracts (https://github.com/andresteingress/gcontracts) und beschäftigt sich in seinem Blog (http://blog.andresteingress.com) mit Themen rund um Android, Scala, Groovy und Grails.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.