2017-10-27 18 views
1

Ich schreibe Kotlin-Code und eine der Features, die es hat, sind Erweiterungsmethoden, die effektiv die gleichen wie normale Funktionen sind, außer dass die Syntax, die Sie verwenden, aussieht wie eine Instanz Methodenaufruf.Wann Erweiterungsmethoden zu verwenden?

Normale Funktion

fun blah(x: Int) { println(x) } 
val f = blah(1) 

Erweiterungsmethode

fun Int.blah() { println(this) } 
val f = 1.blah() 

Soweit ich verstehe, C# Erweiterungsmethoden in ähnlicher Weise arbeiten.

Im Prinzip könnte jede Nicht-Nullartigkeitsfunktion als eine Erweiterungsmethode geschrieben werden, indem der Typ des ersten Parameters links vom Funktionsnamen verschoben und der Funktionskörper angepasst und die Sites dementsprechend aufgerufen werden (wie in diesem Beispiel). .

Sollte ich alle meine Funktionen als Erweiterungsmethoden schreiben, dann? Keiner von denen? Welchen Grundsatz sollte ich verwenden, um zu entscheiden, welche Funktionen normal zu schreiben sind, und welche als eine Erweiterungsmethode für einen der Eingänge zu schreiben?

+0

IMO, sollten Sie vermeiden, Objekte zu erweitern, die Sie nicht besitzen –

+0

@AlexeiLevenkov Das ist über Erweiterungsmethode vs Vererbung. Ich frage nach Erweiterungsmethode vs normale Funktion/statische Methode. – Jesse

+1

@ MarcusHöglund Warum denkst du das? Sie können Ihre Erweiterungsfunktionen erweitern. Sie sind nicht global. Meiner Meinung nach ist das Schreiben von Erweiterungen für Klassen, die Sie nicht besitzen, einer der besten Anwendungsfälle für Erweiterungsfunktionen. Sie können lesbare DSLs schreiben. – marstran

Antwort

0

https://kotlinlang.org/docs/reference/extensions.html#extensions-are-resolved-statically

Erweiterungen sind modifiziere Klassen erstrecken sie sich nicht wirklich statisch

Erweiterungen aufgelöst. Wenn Sie eine Erweiterung definieren, fügen Sie keine neuen Member in eine Klasse ein, sondern machen lediglich neue Funktionen, die mit der Punktnotation auf Variablen dieses Typs aufgerufen werden können.

Wir möchten, dass die Erweiterungsfunktionen hervorzuheben sind statisch versandt, dh sie werden von Empfängertyp nicht virtuell sind

Also alle Ihre Funktionen schreiben können als Erweiterungsmethoden kein guter Ansatz wäre, weil sie werden statisch versendet. Dies beseitigt die Fähigkeit, sie z.B. in abgeleiteten Klassen.

Es ist eher eine Designauswahl, wenn Sie eine Erweiterungsfunktion oder eine "normale" Funktion ausführen.

Ich würde Ihnen folgendes empfehlen: Jedes Mal, wenn Sie eine Funktion, die Sie als Dienstprogramm-Funktion mit einem Dienstprogramm-Klasse wie StringUtil.isNullOrEmpty(String), verwenden Erweiterungsfunktionen schreiben. Verwenden Sie den Rest als "normale" Funktionen.

Lesen Sie auch die Motivation des Kotlin Erweiterungen zu erstellen: https://kotlinlang.org/docs/reference/extensions.html#motivation

+1

Dies gilt für OOP, aber zum Beispiel basiert IEnumerable auf [Prinzipien der funktionalen Programmierung] (https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/) und darin Fall ist es völlig in Ordnung, statische Methoden zu haben. –

+1

Zustimmen. Ich habe keine Ja/Nein-Liste, wenn Sie Erweiterungsmethoden verwenden sollten. Es gibt Situationen (wie die, die du beschrieben hast), wo du sie mehr oder weniger benutzen musst, und andere, wo du sie nicht benutzen solltest. – guenhter

0

Sie Erweiterungen zu schreiben, wenn Sie keinen Zugriff des Quellcodes haben. In Java schreiben Sie Dienstprogrammklassen.

In Kotlin schreiben Sie Erweiterungen Methode.

fun Bar.foo(i: Int): Int = value + i 
bar.foo(1) 

In C# ist es das gleiche, aber Sie verwenden es auch für die Implementierung der Schnittstellenmethode. (Kotlin erlaubt die Implementierung von Schnittstellenmethoden.)

0

Es gibt keine feste Regel, aber Sie sollten nicht alle Ihre normalen Funktionen als Erweiterungsmethoden schreiben.

Sie sind für zwei Dinge in erster Linie verwendet:

Erweiterung Typen, die Sie nicht über die direkte Kontrolle haben. Ein gängiges Beispiel in C# ist die foreach() Funktion, die IEnumerable (Grundtypen für Listen usw.) mit einem Verfahren erstreckt sich eine Aktion auf alle Elemente anwenden:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action) 
{ 
    foreach (T item in enumeration) 
    { 
     action(item); 
    } 
} 

Helper-Funktionen, die häufig Anrufe an Ihre eigenen Klassen vereinfachen , garantieren jedoch keine eigene Methode in Ihrer Klasse oder Sie möchten nicht Teil Ihrer API sein.