2013-05-15 3 views
0

Во время кодирования, я столкнулся с следующей ситуацией:Расчет членов класса

У меня есть класс, давайте назовем его C. Он имеет атрибут A произвольного типа, который должен быть рассчитан первым:

public class C { 
    private int A; 

    public C(...) { 
     ... 
    } 

    public void calculateA() { 
     A = 42; 
    } 

    public int getA() { 
    } 
} 

Мой вопрос теперь в том, как реализовать сорбент getA правильно. Должен ли я проверить, определено ли A и иначе ли исключение?

Или я должен просто позвонить calculateA в getA, если он не установлен?

Что является лучшим выбором для такого рода проблем?


Edit: Хорошо, я дал плохой пример. A не может быть вычислен в конструкторе, потому что метод вычисления вернет новый экземпляр того же класса, что приведет к бесконечной рекурсии.

+3

Почему бы не установить значение по умолчанию для A в вашем конструкторе? – Shaded

+0

Зависит. Но если это целое число, как вы будете отличать его от неустановленного значения? Недопустимое значение '0'? Это долгосрочный расчет (например, действительно ли это имеет значение)? –

+0

Это будет иметь смысл для этого примера. Но в моем случае нет значения по умолчанию, которое имеет смысл. – George

ответ

1

Это вопрос дизайна, несколько неуместный для этого форума.

Если клиент должен позвонить calculateA() до getA(), то getA() может передать исключение, если оно не было рассчитано. Тот факт, что a является примитивным, не имеет значения, вы можете либо инициализировать недопустимое значение - например. если это тип длины объекта, то инициализировать его до -1 - или использовать другую переменную boolean или использовать Integer, которая будет нулевой, независимо.

Понять, что это создает временную зависимость - клиенты должны вызывать методы в фиксированном порядке. Обычно это недоверчиво, но могут быть обстоятельства, чтобы оправдать это, вы должны позвонить Car.start() перед вызовом Car.stop().

С другой стороны, если C «владеет» A, то это его обязанность рассчитать. Он может сделать это несколькими способами:

  • Жадно, в свою <init>, если вся необходимая информация avaialable
  • Лениво/по требованию, но в кэше, вызовите calculateA() первый раз A нужен.
  • Рассчитывать каждый раз, когда он вызывается, хотя getA() может быть вводящим в заблуждение именем в этом случае.
0

Это зависит. Если вычисление статично, вы также можете вызвать функцию calculateA() из конструктора.

public C(...) { 
     ... 
     calculateA() 
    } 

public void calculateA() { 
    A = 42; 
} 

Если договор геттер() предписывает, что только действительные и расчетные значения A будут возвращены, вычислить A перед его возвращением.

Если A не может быть рассчитан по какой-либо причине, и если имеет смысл в вашей программе прекратить выполнение, прежде чем вычислять что-либо еще с недопустимым A, выбросьте исключение.

2

Я думаю -

public class C { 
    private int A = Integer.MIN_VALUE; 
    ... 
    public int getA() { 
     if(A==Integer.MIN_VALUE)// Assume Integer.MIN_VALUE when it is not calculated 
      throw new RuntimeException(); 
     return A; 
    } 
} 

Это не может быть 100% доказательство, как предполагается, Integer.MIN_VALUE не может быть вычислено значение.

Сделайте переменную экземпляра A как целочисленный объект вместо примитива int, поэтому вы можете установить значение null, которое может быть проще определить состояние.

+1

Препятствует тому, что значение «A» равно нулю. – Zutty

+0

Er ... но это будет 0, если явно не указано что-то другое (и предполагает, что 0 не является разумным значением, которое не указано). –

+0

yap его действительно предположение, 0 или MIN_VALUE или MAX_VALUE –

1

Это плохой пример, потому что int является примитивным типом. Это никогда не имеет значения. Он инициализируется до нуля.

Но ваша точка действительна для ссылочных типов.

Я считаю это плохой дизайн, позволяющий ссылаться на частный член. Конструктор должен инициализировать объект, чтобы он был на 100% готов к работе.

+2

Я не согласен с этим. Объект должен быть просто согласован в конце конструктора. В некоторых случаях использования нулевой указатель может быть последовательным, например. Объект, представляющий узел, может иметь родительский узел, который может быть нулевым (случай корневого узла). –

+0

Согласовано. Я думаю о таких случаях, как ребенок списка. Весьма разумно инициализировать его, чтобы указать на пустую реализацию List. Мне не нужно было платить цену за проверку, чтобы увидеть, является ли она пустой при каждом попытке получить к ней доступ. – duffymo

+0

В вашем конкретном случае, зная, что нулевой узел означает, что root - это информация, которая подходит для передачи обратно пользователю. ИЛИ У меня может быть специальный экземпляр Root узла, а метод isRoot() возвращает логическое значение. – duffymo

Смежные вопросы