В Java как и в C++ возможна перегрузка методов. Т.е. возможно создать методы с одинаковыми именами и с разным набором параметров, так, что выбор нужного метода определяется входными параметрами. Так же возможно переопределение родительского метода в классе-наследнике. Для переопределения необходимо, чтобы и название метода, и его параметры соответствовали классу-родителю. Иначе вместо переопределения получится перегрузка. Для того, чтобы минимизировать количество ошибок, в языке Java есть аннотация @Override. В классе-наследнике перед методом, который нужно переопределить, ставится аннотация @Override и компилятор выдает ошибку на этапе компиляции, если вместо переопределения получается перегрузка, т.е. если параметры метода, подлежащего переопределению не соответствуют параметрам метода в родительском классе.
пятница, 14 марта 2014 г.
пятница, 7 марта 2014 г.
Конец про класс и про методы.
Надо бы поместить про класс в предыдущий пост, но блоггер почему-то выдал ошибку, при попытке дописать в пост окончание главы. Поэтому она здесь.
Минимизация сложности класса:
Инициализируйте по возможности все данные-члены!
Если нужен класс-одиночка - используйте синглтон.
Создавайте конструктор полного копирования, если сомневаетесь - для С++ это верно. Нужно ли это в Java, я не помню(.
Причины создания класса.
Причины создания методов во многом такие же, как и причины создания классов. И кроме этого, есть еще несколько:
Цель - чтобы один метод эффективно решал одну задачу и больше ничего не делал.
Имена методов.
Имя метода должно ясно описывать все, что он делает. Т.к. ясно именовать методы в институте не учат, подробно пишу главу из книжки. Далее будет набор правил, позволяющих дать методу понятное имя. Общее правило - если метод трудно назвать, скорее всего, он плохо спроектирован.
begin/end
create/destroy
first/last
get/put
get/set
increment/decrement
insert/delete
lock/unlock
min/max
next/previous
old/new
open/close
show/hide
sourse/target
start/stop
up/down
Желательно, чтобы длина метода была не более 150-200 строк(без комментариев и пустот), обычно метод занимает до 100 строк. Если метод хорошо спроектирован, он уложится в эти рамки (должен).
Функцию следует использовать тогда, когда главной целью метода является возврат конкретного значения, описываемого именем функции.
Про макросы.
Опять же, программируя на С++ я думала, что использовать макросы - это показатель крутости. Но их использование давало иногда такие ошибищи которые очень трудно было отследить и понять. Макконнелл не рекомендует использовать макросы, кроме как в условной компиляции (он ссылается в этом на Страуструпа, а тот, видимо, знает, что говорит)).
Итак, ура. Глава, посвященная методам обработана. Надеюсь, я буду это все использовать. Очень часто при чтении этой книги у меня возникают мысли: а, как просто-то, а я... Учиться мне еще и учиться...
Минимизация сложности класса:
- Включайте в класс как можно меньше методов.
- Неявно сгенерированные методы, которые не нужны, блокируйте.
- Минимизируйте число разных методов, вызываемых классом.
- Избегайте опосредованных вызовов методов из других классов.
Инициализируйте по возможности все данные-члены!
Если нужен класс-одиночка - используйте синглтон.
Создавайте конструктор полного копирования, если сомневаетесь - для С++ это верно. Нужно ли это в Java, я не помню(.
Причины создания класса.
- Моделирование объектов реального мира.
- Моделирование абстрактных объектов.
- Снижение сложности.
- Изоляция сложности.
- Сокрытие деталей реализации.
- Ограничение влияния изменений.
- Упрощение передачи параметров в методы - если несколько методов используют одни и те же данные, вероятно, их нужно выделить в класс.
- Создание центральных точек управления.
- Облегчение повторного использования кода.
- Планирование создания семейства программ.
- Упаковка родственных операций.
- Выполнение специфического рода рефакторинга.
Методы.
Далее в книге идет целая глава, посвященная методам.Причины создания методов во многом такие же, как и причины создания классов. И кроме этого, есть еще несколько:
- снижение сложности;
- формирование понятия промежуточной абстракции;
- предотвращение дублирования кода;
- поддержка наследования - т.к. переопределить небольшой грамотно спроектированный метод проще, чем длинный и плохо спроектированный;
- сокрытие очередности действий;
- сокрытие операций над указателями - неочевидная для меня причина, но очень разумная и приводящая к простоте написания программы;
- улучшение портируемости;
- упрощение сложных булевых проверок - мне раньше казалось, что наличие таких проверок - это показатель "крутости" кода, но они практически нечитаемы после написания и отладки; поэтому и с этой причиной я согласна; попытаюсь впредь делать так;
- повышение быстродействия.
Цель - чтобы один метод эффективно решал одну задачу и больше ничего не делал.
Имена методов.
Имя метода должно ясно описывать все, что он делает. Т.к. ясно именовать методы в институте не учат, подробно пишу главу из книжки. Далее будет набор правил, позволяющих дать методу понятное имя. Общее правило - если метод трудно назвать, скорее всего, он плохо спроектирован.
- Описывайте все, что метод выполняет
- Избегайте невыразительных и неоднозначных глаголов
- Не используйте для различия методов исключительно номера (method1 (), method2 ()...)
- Не ограничивайте длину имени методов искусственными правилами - имя метода длиннее имени переменной; главной задачей имени является ясное и понятное описание сути метода.
- Для именования функции используйте описание возвращаемого значения.
- Для именования процедуры используйте выразительный глагол ( дополняя его объектом, если язык не ОО).
- Определяйте конвенции именования часто используемых операций.
- Дисциплинированно используйте антонимы. Т.к. это тоже одно из моих больных мест, пишу здесь часто используемые:
begin/end
create/destroy
first/last
get/put
get/set
increment/decrement
insert/delete
lock/unlock
min/max
next/previous
old/new
open/close
show/hide
sourse/target
start/stop
up/down
Желательно, чтобы длина метода была не более 150-200 строк(без комментариев и пустот), обычно метод занимает до 100 строк. Если метод хорошо спроектирован, он уложится в эти рамки (должен).
Функцию следует использовать тогда, когда главной целью метода является возврат конкретного значения, описываемого именем функции.
Про макросы.
Опять же, программируя на С++ я думала, что использовать макросы - это показатель крутости. Но их использование давало иногда такие ошибищи которые очень трудно было отследить и понять. Макконнелл не рекомендует использовать макросы, кроме как в условной компиляции (он ссылается в этом на Страуструпа, а тот, видимо, знает, что говорит)).
Итак, ура. Глава, посвященная методам обработана. Надеюсь, я буду это все использовать. Очень часто при чтении этой книги у меня возникают мысли: а, как просто-то, а я... Учиться мне еще и учиться...
суббота, 1 марта 2014 г.
Наследование. Продолжение.
Наследование. Отношение "Является".
Если несколько классов имеют общие данные, но не формы поведения, сделайте общий объект, который включите в эти классы.
Если несколько классов имеют общие формы поведения, но не данные, сделайте эти классы производными от общего базового класса, определяющего общие методы.
- Убедитесь, что вы наследуете только то, что хотите наследовать. Не наследуйте реализацию только потому, что вы наследуете интерфейс. Если интерфейс класса не нужен, а нужна лишь реализация, то лучше включение, а не наследование.
- Не используйте имена непереопределяемых методов базового класса в производных классах.
- Перемещайте общие интерфейсы, данные и формы поведения на как можно более высокий уровень абстракции.
- С подозрением относитесь к классам, объекты которых создаются в единственном экземпляре. Исключение - "Одиночка".
- С подозрением относитесь к базовым классам, имеющим только один производный класс.
- С подозрением относитесь к класам, которые переопределяют метод, оставляя его пустым (убирая реализацию).
- Избегайте многоуровневых иерархий наследования.
- Предпочитайте полиморфизм, а не крупномасштабную проверку типов.
- Множественное наследование - "инструмент, который лучше большую часть времени хранить в гараже под замком". Может пригодится, но может и порождать ошибки (ромбовидная схема!).
Если несколько классов имеют общие данные, но не формы поведения, сделайте общий объект, который включите в эти классы.
Если несколько классов имеют общие формы поведения, но не данные, сделайте эти классы производными от общего базового класса, определяющего общие методы.
вторник, 25 февраля 2014 г.
Продолжаю конспектировать "Совершенный код".
Раздел "Вопросы проектирования и реализации".
Класс может содержать данные или другой класс. Это отношение "Включение".
"Цель наследования - создать более простой код, что достигается путем определения базового класса, идентифицирующего общие элементы двух или более производных классов."
Раздел "Вопросы проектирования и реализации".
Класс может содержать данные или другой класс. Это отношение "Включение".
- Реализуйте с помощью включения отношения "Содержит".
- В самом крайнем случае такое отношение может быть реализовано с помощью закрытого наследования - автор считает, что если получается только так, то это ошибка проектирования и что лучше всего еще раз подумать. Наверное, он прав. Я с таким на практике еще не сталкивалась.
- Настороженно относитесь к классам, содержащим более 7+\-2 данных-членов. Автор считает, что можно класс, содержащий много данных разбить на несколько классов, содержащих небольшое количество данных, и что это поможет упростить работу с данными. Опять же, нужно проверить на математике "Mittens".
"Цель наследования - создать более простой код, что достигается путем определения базового класса, идентифицирующего общие элементы двух или более производных классов."
- Реализуйте при помощи открытого наследования отношения "является". Если производный класс не будет полностью придерживаться контракта, наследоваться не надо.
- Проектируйте и документируйте классы с учетом возможности наследования или запретите его.
- Соблюдайте LSP: клиенты должны иметь возможность использования подклассов через интерфейс базового класса, не замечая никаких различий. Если программист, сделав наследование, забывает о деталях реализации наследников - все ОК. Если он должен думать о семантических различиях реализаций подклассов - наследование зло, тк. не способствует снижению сложности.
Инкапсуляция. Как сделать.
Я перечитала книгу "Эта странная жизнь" про ученого Любищева по ссылке Яны Франк. Ее поразило в нем то, что он записывал все, что делал за весь день в часах и минутах. А меня удивило, что для каждой книги(большой и умной) он писал конспект и критику. Я попробую тоже конспектировать книги по программированию, что я сейчас читаю. Не знаю, насколько меня хватит и насколько это будет полезно.
Итак, сейчас я читаю "Совершенный код" Макконнелла.
За сегодня я читала главы по инкапсуляции из раздела "Качественные интерфейсы классов".
"Без инкапсуляции абстракция обычно разрушается" - эта цитата определяет главный принцип сокрытия данных. Инкапсуляция - один из принципов управления сложностью проекта.
Автор предлагает несколько принципов, позволяющих добиться сокрытия методов и данных классов.
Итак, сейчас я читаю "Совершенный код" Макконнелла.
За сегодня я читала главы по инкапсуляции из раздела "Качественные интерфейсы классов".
"Без инкапсуляции абстракция обычно разрушается" - эта цитата определяет главный принцип сокрытия данных. Инкапсуляция - один из принципов управления сложностью проекта.
Автор предлагает несколько принципов, позволяющих добиться сокрытия методов и данных классов.
- Минимизировать доступность классов и их членов.
- Не предоставлять прямой доступ к данным-членам, а только к методам доступа к данным - с этим пунктом связано у меня больше всего ляпов в моих бывших и настоящих программах. В классах, занимающихся расчетами, обычно очень много данных, которые являются результатом работы. Например, в программе "Mittens". Делать к ним методы доступа я поленилась. А по данному принципу это было необходимо. Хотя, я до сих пор не хорошо понимаю, как можно программы расчетов чего-либо сделать полностью ОО. Мне кажется, не зря до сих пор большинство расчетов остались на фортране.
- Не включать в интерфейс класса детали реализации. В книге есть интересный пример для С++, как скрыть реализацию в заголовочном файле.class A{public: Aresult Funk() const; ...private: AEmplementation *a_emplementation;}В классе AEmplementation находится тот код, который не должен быть доступен классу, использующему класс А.
- Не делайте предположений о том, как класс будут использовать его клиенты. Все, что нужно, должно быть видно из интерфейса. Если какие-то значения нельзя указывать, то проверку значений не нужно отдавать классам клиентам.
- Избегайте использования дружественных классов. Я уже не помню точно, как их делают, т.к. ими не пользовалась. Автор указывает шаблон State(Состояние), как дисциплинированное использование таких классов. Шаблон не знаю. Нужно будет посмотреть потом.
- Не делать метод открытым только потому, что он использует открытые методы, посмотреть, укладывается ли он в абстракцию этого класса.
- Ценить легкость чтения кода выше, чем легкость его написания. Золотые слова! Можно их писать на мониторе, когда лениво печатать.
- Очень осторожно относится к семантическим (смысловым) нарушениям инкапсуляции.
- Остерегаться слишком жесткого сопряжения.
- Минимизировать доступность классов и их членов.
- Избегать дружественных классов
- Делать данные базового класса закрытыми, а не защищенными, чтобы наследники были меньше сопряжены с базовым.
- не включать данные-члены в открытый интерфейс класса.
- остерегаться семантических нарушений инкапсуляции.
- соблюдать "правило деметры" - А знает о Б, но не знает о том, какие методы Б вызывает.
вторник, 18 февраля 2014 г.
Программа для расчета варежек.
Вчера вечером закончила программу по расчету варежек. Точнее, не то что бы я ее закончила совсем. Мне кажется все более разумной чья-то мысль, что программу нельзя закончить, а можно только приостановить разработку на каком-то этапе. Потому что в ходе разработки хочется прибавить туда и сего, и того, и закрутить что-то эдакое. А потом ты понимаешь, что все это не очень-то и важно. И оставляешь минимум, без которого все не будет работать.
Поэтому, вчера я сделала так, чтобы программа считала варежку и отображала расчет на экране, решила, что если мне будет этого не хватать в процессе эксплуатации, я ее допишу, и выложила ее на диске.
Описание программы и инструкция здесь.
Из опыта разработки.
Списки у меня заработали. Разметку я научилась делать. Второй экран в этой проге был не нужен и я с ним не разбиралась. Как и с Intent.
Сейчас читаю Android 4 и Совершенный код. Бегаю между этими двумя книжками, читаю по чуть-чуть и не могу понять, что мне сейчас важнее и интереснее. Макконел легко читается. И у него есть дельные советы. Посмотрим, сколько полезного я извлеку из этой книги.
Поэтому, вчера я сделала так, чтобы программа считала варежку и отображала расчет на экране, решила, что если мне будет этого не хватать в процессе эксплуатации, я ее допишу, и выложила ее на диске.
Описание программы и инструкция здесь.
Из опыта разработки.
Списки у меня заработали. Разметку я научилась делать. Второй экран в этой проге был не нужен и я с ним не разбиралась. Как и с Intent.
Сейчас читаю Android 4 и Совершенный код. Бегаю между этими двумя книжками, читаю по чуть-чуть и не могу понять, что мне сейчас важнее и интереснее. Макконел легко читается. И у него есть дельные советы. Посмотрим, сколько полезного я извлеку из этой книги.
пятница, 7 февраля 2014 г.
Первое приложение готово
У нас несколько дней не было интернета и я не могла смотреть обучающие лекции. Но я застряла на переходах между окнами. Программа выдает ошибку и непонятно почему. Как ее решить самостоятельно я не додумалась. Поэтому стала делать таймер 45/15 из одного окна.
Один таймер я мучила 2.5 дня - это около 8 рабочих часов (когда дети спят и вечером).
Чуточку разобралась с хронометром(Chronometer).
Поняла, что переименовывать проект проще всего с помощью Refactor-> Rename.
И опять на меня находит паника "У меня не получается".
Скачать таймер можно здесь .
Выглядит так.
Назвала в честь Яны Франк. Я сейчас ее фанатка.
Таймер тихий. На заставке показывает время и отсчитывает рабочие минуты и секунды.
Можно запаузить.
Все просто.
Я учусь.
И кусочек кода:
Один таймер я мучила 2.5 дня - это около 8 рабочих часов (когда дети спят и вечером).
Чуточку разобралась с хронометром(Chronometer).
Поняла, что переименовывать проект проще всего с помощью Refactor-> Rename.
И опять на меня находит паника "У меня не получается".
Скачать таймер можно здесь .
Выглядит так.
Назвала в честь Яны Франк. Я сейчас ее фанатка.
Таймер тихий. На заставке показывает время и отсчитывает рабочие минуты и секунды.
Можно запаузить.
Все просто.
Я учусь.
И кусочек кода:
// Хронометр. Отсчитывает время. Связваю его с виджетом
final Chronometer cr = (Chronometer)findViewById(R.id.chronometer1);
// Запускаю при создании программы
cr.start();
// Привязываю обработчик события тика таймера.
// Это новый класс реализующий интерфейс OnChronometerTickListener
cr.setOnChronometerTickListener(new OnChronometerTickListener(){
. . .
Продолжение следует.
Подписаться на:
Сообщения (Atom)
