Материал предоставлен https://it.rfei.ru

Вопрос о реализации класса

Рассмотрим следующие интерфейсы.

// Многоугольник
trait Polygon {

  // Количество сторон
  def sides: Int

  // Периметр
  def perimeter: Double

  // Площадь
  def area: Double

}
// Правильный выпуклый многоугольник
trait RegularConvexNgon
  extends Polygon {

  // Длина стороны
  def side: Double

  // Радиус описанной окружности
  def circumradius = side / (2 * math.sin(math.Pi / sides))

  // Радиус вписанной окружности
  def apothem = circumradius * math.cos(math.Pi / sides)

  // Периметр
  def perimeter = sides * side

  // Площадь
  def area = sides * side * apothem / 2

}

Какие методы необходимо реализовать конкретному классу, расширяющему интерфейс RegularConvexNgon?

Какие методы необходимо реализовать конкретному классу, расширяющему интерфейс Polygon?

Отметьте корректные варианты реализации класса EquilateralTriangle, моделирующего равносторонний треугольник.

  class EquilateralTriangle(val side: Double)
    extends RegularConvexNgon {

    def sides = 3

  }
  
  class EquilateralTriangle(val side: Double,
                            val sides: Int = 3)
    extends RegularConvexNgon
  
  class EquilateralTriangle(var side: Double)
    extends RegularConvexNgon {

    val sides: Int = 3

  }
  
7 лет назад

Здравствуйте,

не могу найти ошибку в задании, уверен, что ошибка именно в третьей части, т.к.:
- в первой части классу, расширяющему интерфейс RegularConvexNgon необходима реализция методов sides и side (только они не реализованы ни в интерфейсе RegularConvexNgon, ни в расширяемом им интерфейсе Polygon)
- во второй части класс обязан реализовать все три объявленных метода интерфейса Polygon
- в третьей части Вариант 1 - ВЕРНО
уверен, что ошибка именно в этой части, но хотелось бы узнать где и почему (хотя при компиляции все 3 варианта ошибок не возвращают)

С уважением,
Дмитрий

7 лет назад

Понял, где ошибался.
Правда остался вопрос - почему при выполнении некорректного варианта реализации класса получаю результат вычислений? И если это работает и работает верно, почему нельзя применять?

scala> trait Polygon {
     |   def sides: Int
     |   def perimeter: Double
     |   def area: Double
     | }
defined trait Polygon

scala> trait RegularConvexNgon extends Polygon {
     |     def side: Double
     |     def circumradius = side / (2 * math.sin(math.Pi / sides))
     |     def apothem = circumradius * math.cos(math.Pi / sides)
     |     def perimeter = sides * side
     |     def area = sides * side * apothem / 2
     | }
defined trait RegularConvexNgon

scala> class EquilateralTriangle(val side: Double, val sides: Int = 3) extends RegularConvexNgon
defined class EquilateralTriangle

scala> var t = new EquilateralTriangle(9)
t: EquilateralTriangle = EquilateralTriangle@110e9982

scala> println(t.side + "\n" + t.sides + "\n" + t.circumradius + "\n" + t.apothem + "\n" + t.perimeter + "\n" + t.area)
9.0
3
5.196152422706632
2.5980762113533165
27.0
35.07402885326977

С уважением,
Дмитрий

7 лет назад

Добрый день, Дмитрий.

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

Вторая, возможно, в том, что автор предполагал “плохой техникой” такую реализацию. Вот давайте рассуждать от конца:

Вы определяете класс EquilateralTriangle реализуя черты RegularConvexNgon, в котором определены 3 своих (side, circumradius, apothem) и 3 унаследованных метода (perimeter, area, sides).

Я обращаю ваше внимание на то, что всё это методы.

Реализованы уже четыре метода (circumradius, apothem, perimeter, area). Чтобы закончить корректное определение класса вам необходимо реализовать ещё два метода: side и sides.

При определении класса вы указываете на то, какие параметры вы будете принимать в конструкторе класса. Они вовсе не обязаны впоследствии быть публичными.

Речь не идёт в этот момент о том, как вы реализовываете сами методы.

Честно говоря, я считаю такую реализацию, которая сейчас компилируется, ошибкой. Почему создатели Scala пошли на такую имплицитную реализацию методов и перекрытие имён мне непонятно. Точнее, мне понятно, но я не считаю это решение инженерно-правильным, поскольку очевидно, что вы не можете сказать по коду класса в каком конкретно месте реализуются методы side и sides.

С уважением,
Станислав Лахтин

7 лет назад

Добрый вечер.

В догонку.

Обратите внимание на мой старинный блог. Я когда-то писал довольно много о Scala. Но много меньше, чем мне того хотелось бы.

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

Обстоятельства складываются так, что мы уже несколько лет находимся на другом технологическом стеке и некоторые вещи начали забываться.

С уважением,
Станислав Лахтин

7 лет назад

Здравствуйте, Станислав Евгеньевич.

Спасибо за доходчивый ответ. И отдельное спасибо за «в догонку». Вижу в блоге много интересного, так что буду “догонять” :)

С уважением,
Дмитрий

Ваш комментарий

Комментирование доступно только для авторизованных пользователей.