Наследование

Создайте интерфейс Figure, который означает геометрическую фигуру. По ходу решения постоянно пишите код, который проверяет работоспособность всех реализованных функций.

  1. Добавьте методы double area() и double perimiter(), которые возвращают, соответственно, площадь и периметр фигуры. Добавьте метод String info() для указания краткой информации о фигуре. Там будет возвращаться текст типа “квадрат со стороной 7”, “круг радиуса 22” и т.п.
  2. Добавьте классы
    • круг
    • квадрат
    • прямоугольник
    • ромб
    • равносторонний треугольник
    • прямоугольный треугольник

    Они должны реализовывать интерфейс Figure и переопределять все необходимые методы. В конструкторы классов должны передаваться размеры: ширина и высота для прямоугольника, сторона для квадрата, радиус для круга, сторона для равностороннего треугольника, две стороны прямоугольного треугольника, длины диагоналей у ромба.

    Для проверки создайте массив Figure[], заполните его всеми видами фигур и в цикле распечатайте информацию о каждой фигуре, ее площадь и периметр.

  3. В прошлой задаче все классы напрямую наследовали Figure. Теперь унаследуйте прямоугольник от квадрата или квадрат от прямоугольника. Подумайте, как будет лучше.
  4. Добавьте абстрактный класс Параллелограм. От него должны наследоваться прямоугольник, квадрат и ромб. Параллелограмм должен хранить длины двух своих сторон и уметь вычислять периметр. А вот вычисление площади должно быть абстрактным. Соответственно, уберите вычисление периметра из классов наследников.
  5. Мы хотим иметь возможность вычислять ёмкость фигуры, это отношение ее площади к квадрату периметра. Но мы не хотим программировать одно и то же для каждой фигуры. Есть такие варианты, реализуйте их:
    1. Добавьте в интерфейс Figure статический метод double capacity(Figure f).
    2. Добавьте в интерфейс Figure метод по умолчанию default double capacity(). Разберитесь самостоятельно, что это за методы по умолчанию. Переопределите вычисление ёмкости в одной из фигур, чтобы вычисление стало более эффективным.

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

    Кстати, у какой фигуры максимальная ёмкость?

  6. (*) можно сделать дополнительно класс Треугольник, от него наследуются прямоугольный и равносторонний треугольники. Он сможет вычислять и свою площадь, и свой периметр по трем сторонам.
  7. (**) Вообще-то квадрат тоже ромб. Но пока это никак не отражено в наследовании. Если хочется сделать квадрат и ромбом, и прямоугольником, два последних класса должны стать интерфейсами. Т.е. все должно стать интерфейсами. Сделайте все интерфейсами, в интерфейсах вместо полей сделайте методы с именами типа getR(), например, чтобы получить радиус круга. Реализуйте каждый интерфейс классом с именем типа RectangleImpl, SquareImpl. Понадобавляйте в интерфейсы необходимое количество default методов. Для создания фигур в интерфейсы нужно добавить статические методы create(), например, в Circle будет метод static Circle create(), который возвращает CircleImpl.

Интерфейсы, лямбда выражения и анонимные классы

  1. Создайте интерфейс Printable с одним методом void print(), этот метод означает, что объект печатает что-то на экране. Сделайте так, что класс Drawing из прошлого семестра реализует этот интерфейс. Проверьте, что получилось.
  2. Создайте класс PrintableLetter, реализующий интерфейс Printable. Пользоваться классом нужно так:

       PrintableLetter pl = new PrintableLetter("x", 10);
       pl.print(); //печатает букву x 10 раз
    
  3. Создайте класс PrintableString, реализующий интерфейс Printable, этот класс хранит строку, пользоваться им нужно так:

       PrintableString ps = new PrintableString("asdf");
       ps.print(); //печатает asdf
    
  4. Создайте массив типа Printable[], заполните его 1) Drawing 2) PrintableLetter 3) PrintableString 4) анонимным классом 5) лямбда выражением. В цикле попросите всех что-нибудь напечатать.