Комментарии (86)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
nescafe
Уровень 30
25 марта, 16:50
оператор instanceof https://javarush.com/groups/posts/2018-kak-rabotaet-operator-instanceof
public class Animal {

}

public class Cat extends Animal {

}

public class MaineCoon extends Cat {

}

Cat cat = new MaineCoon(); // * Объект-потомок всегда можно присвоить в переменную-предка. Пока просто запомни это, а в следующих лекциях мы еще разберем этот процесс.
System.out.println(cat instanceof Cat); //true
System.out.println(cat instanceof MaineCoon); //true
nescafe
Уровень 30
25 марта, 16:32
Сокурсники, в недрах этих задач я нашёл комментарий Кирилла с феноменальным объяснением интерфейсов на кончиках пальцев. В один пост не влезло, поэтому бью на 2 части и предлагаю поднять это сокровище в ТОП. Более лучшего, человеческого объяснения я ещё не встретил, поехали: «Когда мы implements какой-либо интерфейс на свой класс, мы обязуемся описать те методы, что объявлены(абстрактными) в интерфейсе, который мы implements. Пример, передо мной стоит лампа, на ней кнопочка - включить и кнопочка выключить. Я нажимаю на кнопочку включить - лампа включается, нажимаю на выключить - лампа выключается. Это интерфейс для пользователя. Мне, как пользователю, абсолютно все равно что происходит внутри лампы при нажатии на кнопку "Включить" или "Выключить", для меня главное - результат(есть свет или его нет). Если этот пример спроецировать на Жаву, то - 1) У нас есть интерфейс SwitchAble(Переключаемое); 2) В этом интерфейсе объявлены 2 абстрактных метода - TurnOn(включить) и TurnOff(выключить), то есть они без реализации(без тела); 3) Мы создаем класс нашей лампы(public class Lamp); 4) Имплементируем интерфейс SwitchAble( public class Lamp implements SwitchAble); 5) С этого момента мы обязаны переопределить "пустые" методы интерфейса SwitchAble в нашем классе Lamp(иначе не скомпилируется) 6) В переопределенных методах будет описана вся реализация для методов "Включить" и "Выключить"(как подается ток, как убирается ток, куда этот ток идет и тд и тп). 7) Интерфейс - это обязательство того , что твой класс будет УМЕТЬ делать то, что описано(объявлено) в интерфейсе. В данном случае наша лампа умеет переключаться(вкл, выкл). 8) Для примера мы создаем еще один класс - Toaster(Тостер) и имплементируем наш интерфейс SwitchAble, после этого переопределяем все его методы(так как мы обязаны это сделать), но переопределяем по другому(ведь лампа включается и выключается не так как тостер).» Продолжение в посте ниже...
nescafe
Уровень 30
25 марта, 16:32
Продолжение: « 9) Теперь у нас 2 класса, которые умеют "переключаться" - лампа и тостер и мы можем делать такую вещь: SwitchAble thing1 = new Lamp(); //мы присвоили переменной типа "переключаемое" Лампу SwitchAble thing2 = new Toaster();//мы присвоили переменной типа "переключаемое" Тостер thing1.turnOn(); //мы включили лампу thing2.turnOn(); //мы включили тостер То есть мы объединили наши разные вещи(Тостер и Лампу) под одним интерфейсом. То есть, в теории, можно насоздавать объектов, которые умеют переключатся(вкл и выкл)(телевизор, кондиционер, холодильник и другие бытовые приборы). Потом запихать их в один лист List<SwitchAble> list = new ArrayList<>(); //создали лист, который может принимать в себя все что SwitchAble(его имплементации) list.add(new Tel() ) ; //добавили телефон list.add(new Lamp() ); //добавили лампу list.add(new Toaster() ); //добавили тостер list.add(new Conditioner() ); //добавили кондиционер list.add(new Fridge() ); //добавили холодильник for(SwitchAble device: list){ device.turnOn(); } //пробегаемся по каждому элементу листа бытовых приборов и каждому прибору вызываем метод "Включить" Теперь мы включили все приборы, вот и умный дом запрограммирован». Конец цитирования, все овации автору комментария Кириллу. Всё получится!
nescafe
Уровень 30
25 марта, 16:26
Долго не понимал суть интерфейсов. Ведь примеры очень простые и неочевидно зачем нужно создавать интерфейс, вместо того, чтобы сразу в классе прописать эти 1 или 2 метода. Задал вопрос другу-кодеру, вот что он рассказал. Возможно кому-то поможет разобраться. "Интерфейс если на пальцах. У тебя должно быть много разных классов. Грузовик мопед седан спорткар итд. они все разные. Но совершенно точно, что все они должны мочь ездить, поворачивать и тормозить. И чтобы тебе не забыть прописать каждое из этих свойств в каждом классе, ты создаешь интерфейс. В котором 3 функции - ехать, повернуть, тормозить. И подключаешь его к своим классам с машинами. Теперь, когда он подключен, ты не можешь не расписать эти три функции внутри этих машин, тк тебе ошибка вылетит. Это нужно, чтобы когда ты в начале создаешь архитектуру классов, добавил везде интерфейсов, и потом, когда будешь писать наполнение классам, то не забудешь заимплеменитть важные функции. Это самое простое из объяснений зачем."
nescafe
Уровень 30
25 марта, 16:22
ИНТЕРФЕЙСЫ ✔ У интерфейсов все методы — public. ✔ Содержит только абстрактные методы (abstract писать не нужно). ✔ Интерфейс может наследоваться от нескольких интерфейсов (от классов НЕ наследуется). ✔ Класс может наследоваться от нескольких интерфейсов. ▶ Допустим есть интерфейс Animal и класс Tiger, который наследует этот интерфейс. Создаём объект типа Tiger и присваиваем ссылку на него в переменную типа Animal. Animal tiger = new Tiger(); Теперь переменная tiger может обращаться только к тем методам, которые прописаны в интерфейсе Animal.
nescafe
Уровень 30
19 марта, 16:37
Про сужение и расширение Ссылка на объект - это что-то вроде пульта от ТВ (т.е. от объекта). Без пульта объект не имеет значения и удаляется. Если у нас иерархия Animal --> Pet --> Dog и мы создаем ссылку (пульт) типа Dog на объект Dog, то на этом пульте будут все кнопки (методы) этого класса и родительских классов: Pet и Animal. Т.е. у пульта типа Dog для объекта Dog - максимальное число кнопок, потому что они наследуются от всех классов-родителей, и объект Dog может реализовывать себя на все 100%. Если мы сделаем пульт (ссылку) для управления Dog из класса-родителя, к примеру Pet, то объект Dog не сможет раскрыть весь свой потенциал, потому что не все кнопки (методы) будут на пульте (в ссылке). Pet pet = new Dog(); Это сужение (мы убавили кнопок) Если у нас пульт типа Pet от объекта Dog, и мы хотим присвоить значение этотого пульта к пульту типа Dog, то говорим компилятору чтоб он добавил кнопок, потому что мы хотим управлять объектом по полной, и в скобках указываем тип пульта который нам нужен : Pet pet = new Dog(); Dog dog = (Dog) pet; Это расширение (мы добавили кнопок)
nescafe
Уровень 30
19 марта, 16:31
По поводу комментариев о расширении/сужении. class Whale extends Cow Само слово extends - расширяет. То-есть, класс Кит берет все методы и переменные класса Корова и расширяет их - добавляет свои. Присвоение Cow cow = new Whale(); - это сужение, потому как мы обрезаем (сужаем) функционал созданного объекта Кит до функционала коровы, то-есть, можем вызвать только методы, объявленные в классе Корова и обратиться только к переменным класса Корова. Несмотря на то, что наш объект класса Кит, мы не можем вызвать его методы, значит мы урезали (сузили) функционал объекта присвоив его переменной типа родителя. А про абсурдность наследования кита от коровы - это уже издержки игрового объяснения) Правильно сказал Алексей Еловик - мы ж с Вами на другой планете и вообще мы все роботы и не знаем о коровах и китах планеты Земля)
nescafe
Уровень 30
19 марта, 16:29
✦ Наследовать и переопределять можно только нестатические методы. Статические методы не наследуются и, следовательно, не переопределяются. ✦ static, final и final static поля НАСЛЕДУЮТСЯ (если они не private). ✦✦✦ Если в подклассе Lion переопределить метод sayMay() суперкласса Cats, то при вызове объектом подкласса Lion метода sayMay() ─ будет вызывать именно переопределённый метод, а не метод суперкласса. ► НО!!! Объект подкласса Lion может вызвать метод sayMay() СУПЕРКЛАССА, даже если он в своём классе Lion переопределён ─ для этого нужно написать "super.sayMay();" в любом нестатическом методе подкласса Lion в нужном тебе месте. ↓ Это может понадобится, если реализация метода суперкласса на 100% подходит подклассу, но надо добавить ещё какое-то количество функционала, а не полностью изменять метод суперкласса. ✦✦✦ Набор методов, которые можно вызвать у переменной, определяется типом переменной. А какой именно метод/какая реализация вызовется, определяется типом/классом объекта, ссылку на который хранит переменная.
nescafe
Уровень 30
18 марта, 17:06
Главное, не в каком классе написан метод, а какой тип (класс) объекта, у которого этот метод вызван. — Ясно. — Наследовать и переопределять можно только нестатические методы. Статические методы не наследуются и, следовательно, не переопределяются. Запомни главное правило: Набор методов, которые можно вызвать у переменной, определяется типом переменной. А какой именно метод/какая реализация вызовется, определяется типом/классом объекта, ссылку на который хранит переменная. ) Расширение и сужение типов. Для ссылочных типов, т.е. классов, приведение типов работает не так, как для примитивных типов. Хотя у ссылочных типов тоже есть расширение и сужение типа. Пример: Расширение типа Описание
Cow cow = new Whale();
Классическое расширение типа. Теперь кита обобщили (расширили) до коровы, но у объекта типа Whale можно вызывать только методы, описанные в классе Cow. Компилятор разрешит вызвать у переменной cow только те методы, которые есть у ее типа — класса Cow. Сужение типа Описание Cow cow = new Whale(); if (cow instanceof Whale) { Whale whale = (Whale) cow; } Классическое сужение типа с проверкой. Переменная cow типа Cow, хранит ссылку на объект класса Whale. Мы проверяем,что это так и есть, и затем выполняем операцию преобразования (сужения) типа. Или как ее еще называют– downcast.
Cow cow = new Cow();
Whale whale = (Whale) cow; //exception
Ссылочное сужение типа можно провести и без проверки типа об-а. При этом,если в переменной cow хранился объект не класса Whale, будет сгенерировано исключение – InvalidClassCastException. 6) Вызов оригинального метода Иногда тебе хочется не заменить унаследованный метод на свой при переопределении метода, а лишь немного дополнить его. В этом случае очень хочется исполнить в новом методе свой код и вызвать этот же метод, но базового класса. И такая возможность в Java есть. Делается это так: super.method().
nescafe
Уровень 30
17 марта, 17:23
Агрегация — это когда объект является частью другого объекта и при этом этот 1 объект ОДНОВРЕМЕННО может являться частью любого количества других объектов! Например Студент входит в Группу любителей физики. Студент одновременно может входить в любое количество других Групп ─ хоть в миллиард Групп! :D Композиция — это когда объект является частью другого объекта и не может одновременно являться частью любого второго объекта. Например Машина и Двигатель. Хотя двигатель может быть и без машины, но он 1 не может быть в двух или трех машинах одновременно. В отличии от студента, который может быть частью триллиона Групп одновременно. Да, во вторую машину можно поставить точно такой же двигатель, но это уже будет СОВСЕМ ДРУГОЙ ОБЪЕКТ. Лайк за картинку, старался! :)