Почему в коде Android есть публичные поля?

Существует много вопросов и ответов об использовании открытых полей в объектно-ориентированном программировании, и большинство из них рекомендует не использовать публичные поля по многим причинам.

Но когда я посмотрел на Android-код, я обнаружил, что некоторые классы используют публичные поля. Например Android.view.View имеет общедоступные поля mCachingFailed и mAttributes.

Почему они публичные? Трудно думать, что это ошибка в Google и AOSP.

Ответ 1

Ошибочно иметь публичные поля. Это не означает, что, как отмечается в примечании к награде, "ООП-фундаментальное нарушение". После того, как все эти два класса (для большинства целей) идентичны:

public class DemoA {
  public int field;
}

public class DemoB {
  private int field;

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

То есть, если вы намерены, чтобы вызывающие лица имели прямой доступ к чтению и записи в поле, добавляющее геттер, а сеттер может просто быть дополнительной котельной.

Преимущество геттеров и сеттеров, даже если они не выполняют никакой другой работы, кроме чтения и записи в поля, заключается в том, что они абстрагируют тот факт, что данные хранятся в поле вообще. Он может храниться во внешнем источнике данных или вычисляться "на лету" или независимо от того, что вам нужно, и вызывающим абонентам не нужно беспокоиться о том, как осуществляется поведение. Это, безусловно, хорошая практика в целом, поскольку она отделяет проблемы вызывающих абонентов (API) от ваших проблем (реализация).

Однако иногда это просто излишнее, и вполне разумно публиковать публичные поля, если это лучший способ обеспечить поведение, которое вам нужно для звонков. Чаще всего это делается для типов значений, классов, которые существуют исключительно для группировки нескольких полей вместе. Там мало пользы для написания десятков геттеров и сеттеров, когда все, что вам нужно, чтобы сделать класс, можно сделать, просто сделав поля общедоступными.

Как практический вопрос, Android вызывает дополнительную озабоченность. Вызов метода дорог, и количество методов, которые приложение может (легко) определить, ограничено ~ 65k. В случаях, когда это безопасно, разоблачение поля напрямую снижает накладные расходы метода на два и экономит ценное время CPU. Это может показаться не очень большим, но оно быстро складывается.

Ответ 2

Посмотрите этот раздел с сайта developer.android.com:

На родных языках, таких как С++, общепринятой практикой является использование геттеров (i = getCount()) вместо прямого доступа к полю (i = mCount). Эта является отличной привычкой для С++ и часто практикуется в другом объекте таких как С# и Java, поскольку компилятор обычно может встроить доступ, и если вам нужно ограничить или отладить доступ к полю вы можете добавить код в любое время.

Однако это плохая идея для Android. Виртуальные вызовы методов дороже, гораздо больше, чем поиск в полевых условиях. Это разумно придерживаться общих методов объектно-ориентированного программирования и геттеры и сеттеры в публичном интерфейсе, но внутри класса вы должен всегда напрямую обращаться к полям.

Без JIT прямой доступ к полю примерно в 3 раза быстрее, чем вызов тривиальный геттер. С JIT (где прямой доступ к полю дешевле, чем доступ к локальному), прямой доступ к полям примерно в 7 раз быстрее, чем вызывая тривиальный геттер.

Обратите внимание: если вы используете ProGuard, вы можете использовать миры, потому что ProGuard может использовать для вас дополнительные инструменты

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

Скорее всего, это причина, по которой вы видите публичные поля в AOSP.