Не используйте типовые тесты, объявите doTheTask?

Я прохожу через Java для всех от Cay Horstmann.

Я немного смущен, когда он говорит:

Не используйте типовые тесты

Это об использовании instanceof оператор для тестов конкретного типа, чтобы реализовать поведение, которое варьируется в зависимости от каждого класса (взято прямо из книги):

if (q instanceof ChoiceQuestions) //Don't do this
{
   //Do the task the ChoiceQuestion way
}
else if (q instanceof Question)
{
   //Do the task Question way
}

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

Лучше добавить класс NumericQuestion к программе. Ничего не нужно менять, так как мы используем полиморфизм, а не тесты типов. Если вы когда-нибудь пытаетесь использовать тесты типа в иерархии классов, пересмотрите и используйте вместо этого полиморфизм. Объявить метод doTheTask в суперклассе, переопределите его в подклассах и вызовите q.doTheTask()

Что я не понимаю, так это последний абзац, приведенный выше. Может кто-нибудь подсунуть мне пример того, что это значит, пожалуйста? (Я отчасти визуальный ученик). Как мы можем сделать это без использования тестов?

3 ответа

Решение

Дело в том, что вместо этого:

if (q instanceof ChoiceQuestions) //Don't do this
{
   //Do the task the ChoiceQuestion way
}
else if (q instanceof Question)
{
   //Do the task Question way
}

Вы должны сделать это:

q.doTheTask();

где Question класс содержит:

public void doTheTask(String someParameter){
    //Do the task Question way
}

и ChoiceQuestion класс содержит

public void doTheTask(String someParameter){
    //Do the task the  ChoiceQuestion way
}

Затем, когда вы получаете новый класс DrawQuestion будет содержать

public void doTheTask(String someParameter){
    //Do the task the DrawQuestionway
}

но ни один из кода, который вызывает doTheTask() придется менять! Там нет риска, как это с if (q instanceof ChoiceQuestions) шаблон, забыв добавить новую логику. И (это на самом деле самая важная часть в долгосрочной перспективе) вся логика, которая касается конкретного вида Question сосредоточено в одном классе, а не распределено по всем частям приложения.

Вы должны понимать, что класс отвечает за свое поведение, а не за вызывающую часть из exmaple. Я узнал это как принцип "стол должен нарисовать сам":

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

Художник:

if (q instanceof Table) //Don't do this
{
   //paint table
}
else if (q instanceof Closet)
{
   //paint closet
}

То, что вы делаете, это то, что вы заставляете всю мебель расширять класс мебели, который знает метод paintThySelf(), Так что теперь художник просто делает

q.paintThySelf()

И если вы добавите класс кафедры, вам придется добавить paintThySelf() метод, и вы можете нарисовать его.

В качестве принципа проектирования предпочтение отдается созданию подкласса с другим (переопределенным) поведением по сравнению с использованием instanceof контролировать поведение.

Другие вопросы по тегам