2015-11-19 5 views
15

Es gibt viele Fragen und Antworten zur Verwendung von öffentlichen Feldern in der objektorientierten Programmierung, und die meisten von ihnen empfehlen, öffentliche Felder aus vielen Gründen nicht zu verwenden.Warum hat ein android Code öffentliche Felder?

Aber als ich in den Android-Code schaute, fand ich heraus, dass einige Klassen öffentliche Felder verwenden. Zum Beispiel hat Android.view.View öffentliche Felder mCachingFailed und mAttributes.

Warum sind sie öffentlich? Es ist schwer zu glauben, dass dies ein Fehler bei Google und AOSP ist.

+0

Warum fragen Sie uns? Fragen Sie die Autoren. Sie wissen. – EJP

+2

@EJP Sie sagten, dass sie es absichtlich in Android Issue Tracker getan hatten (sie benutzten public + '@ hide' anstelle von privat) Ich habe keinen persönlichen Kontakt zu Android Entwicklern, und ich denke Android Problem Tracker ist nicht für Q & A. –

+0

Höchstwahrscheinlich aus Leistungsgründen, d. H. Klassen aus anderen Paketen müssen auf einigen kritischen Pfaden auf sie zugreifen. In der Tat verweist 'android.widget.ListView' auf' drawChild (Canvas Canvas, View Kind, long drawingTime) '. Aber ohne Kommentar von maßgeblichen Persönlichkeiten ist dies nur eine Vermutung. – Kai

Antwort

13

Es ist nicht von Natur aus ein Fehler, öffentliche Felder zu haben. Es ist nicht, wie die Kopfgeldnote andeutet, eine "OOP-Grundrechtsverletzung". Nach all diesen zwei Klassen (für die meisten Zwecke) identisch sind:

public class DemoA { 
    public int field; 
} 

public class DemoB { 
    private int field; 

    public int getField() { return field; } 
    public void setField(int value) { field = value; } 
} 

Das heißt, wenn Sie beabsichtigen für Anrufer direkt lesen zu haben und auf ein Feld Schreibzugriff sein, einen Getter und Setter-Zugabe kann nur extra Kesselplatte.

Der Vorteil von Getter und Setter, auch wenn sie nichts anderes tun, als Felder zu lesen und zu schreiben, besteht darin, dass sie die Tatsache abstrahieren, dass die Daten überhaupt in einem Feld gespeichert sind. Es könnte in einer externen Datenquelle gespeichert werden oder im laufenden Betrieb oder was auch immer Sie möchten, und Anrufer müssen sich nicht darum kümmern, wie das Verhalten implementiert wird. Dies ist definitiv eine gute Praxis im Allgemeinen weil es die Anrufer Anliegen (die API) von Ihren Bedenken (die Implementierung) trennt.

Aber manchmal ist es einfach zu viel, und es ist völlig in Ordnung, öffentliche Felder verfügbar zu machen, wenn das das beste Verhalten ist, das Ihre Anrufer benötigen. Meistens geschieht dies für value types, Klassen, die nur existieren, um eine Anzahl von Feldern zusammenzufassen. Es macht wenig Sinn, die Anzahl der Getter und Setter zu notieren, wenn alles, was Sie brauchen, erledigt werden kann, indem Sie einfach die Felder veröffentlichen.

Aus praktischen Gründen hat Android ein zusätzliches Problem. Methodenaufrufe sind teuer und die Anzahl der Methoden, die eine App (leicht) definieren kann, ist limited to ~65k. In Fällen, in denen dies gefahrlos möglich ist, reduziert das direkte Aussetzen eines Felds den Methodenaufwand um zwei und spart wertvolle CPU-Zeit. Das scheint nicht viel, aber es summiert sich schnell.

+0

Außerdem bin ich einmal über einen Artikel gestolpert (kann aber nicht mehr finden) über den Zugriff auf ein Feld direkt (etwas) schneller als durch Getter und Setter (auf manchen Architekturen). Dies wäre nur in Hochleistungsanwendungen messbar. Ich weiß es nicht, aber vielleicht wurden die öffentlichen Felder aus diesem Grund in einigen Klassen implementiert. Zum Beispiel könnte auf die View-Klassenfelder oft (und vorzugsweise so schnell wie möglich) zugegriffen werden. Ich weiß nicht, ob das noch stimmt, aber ich wollte es trotzdem notieren. –

+0

Sicher, es ist potenziell geringfügig schneller. Aber sowohl der Compiler als auch das JIT könnten potentiell Getter/Setter dahingehend optimieren, dass sie tatsächlich Feldzugriffe sind, so dass es wahrscheinlich einen sehr begrenzten Overhead gibt. Mehr noch, Sie sollten es vermeiden, Designentscheidungen aus Effizienzgründen zu treffen, bis Sie sicher sind, dass es ein Engpass ist. Die Kosten für das Schreiben von schlechtem Code im Namen der Effizienz sind viel höher als die Kosten für leichte Ineffizienzen, mit denen manchmal gute Muster einhergehen. – dimo414

+0

@mad_manny Ich denke, das ist was du liest: http://developer.android.com/training/articles/perf-tips.html#GettersSetters "Es ist vernünftig, gängigen objektorientierten Programmierpraktiken zu folgen und Getter und Setter in der öffentliche Schnittstelle, aber innerhalb einer Klasse sollten Sie immer direkt auf Felder zugreifen. " –

6

Schauen Sie sich diesen Abschnitt aus developer.android.com:

In Muttersprachen wie C++ ist es gängige Praxis, Getter zu verwenden (i = getCount()), statt das Feld für den Zugriff direkt (i = MCOUNT). Diese ist eine hervorragende Angewohnheit für C++ und wird oft in anderen Objekt orientierten Sprachen wie C# und Java praktiziert, weil der Compiler kann normalerweise Inline-Zugriff, und wenn Sie Feldzugriff einschränken oder debuggen können Sie den Code hinzufügen Jederzeit.

Dies ist jedoch eine schlechte Idee für Android. Virtuelle Methodenaufrufe sind teuer, viel mehr als Instanz-Feld-Lookups. Es ist vernünftig zu folgen üblichen objektorientierten Programmierpraktiken und haben Getter und Setter in der öffentlichen Schnittstelle, aber innerhalb einer Klasse sollten Sie immer Felder direkt zugreifen.

Ohne JIT ist direkter Feldzugriff etwa 3x schneller als das Aufrufen eines trivialen Getters . Mit dem JIT (wo direkter Feldzugriff so billig ist wie Zugriff auf eine lokale), ist direkter Feldzugriff etwa 7x schneller als Aufruf eines trivialen Getter.

Beachten Sie, dass, wenn Sie ProGuard verwenden, können Sie das Beste aus beiden Welten haben kann, weil ProGuard Accessoren für Sie

http://developer.android.com/training/articles/perf-tips.html#GettersSetters

Wahrscheinlich Inline kann, ist dies der Grund, warum Sie öffentlich zu sehen Felder in AOSP.

+0

Es ist großartig zu wissen, dass es auf der offiziellen Android Entwickler-Website erwähnt wurde. Wir müssen jedoch beachten, dass es auf der Webseite darum geht, "interne" Getter/Setter zu vermeiden und nichts über die Gültigkeit eines öffentlichen Feldes zu erwähnen, auf das direkt von außerhalb der Klasse zugegriffen werden kann. (Siehe auch: http://stackoverflow.com/questions/6716442/android-performance-avoid-internal-getters-setters) – Taka