Тип личности здесь не очень актуален. Наследование от другого класса открывает открытые методы этого класса независимо от любого типа себя. Таким образом, можно сказать, что любое наследование класса с открытыми методами нарушает принцип единой ответственности.
Если trait
предназначен для использования для внедрения зависимостей, тогда он должен сделать свои методы protected
, чтобы они не отображались.
trait Output {
protected def output(str: String): Unit
}
trait ConsoleOutput extends Output {
protected override def output(str: String): Unit = println(str)
}
Комментарий к принятому ответу
В принятом ответе утверждается, что «Ответственность за предоставление вывода по-прежнему лежит на компоненте, реализующем Output
». Это неверно и показывает путаницу между типом и реализацией.
Поведение объекта определяется его типом, а не его реализацией (принцип подстановки Лискова). Тип - это контракт, который сообщает пользователю, что может сделать объект. Следовательно, именно тип определяет обязанности, а не реализация .
Тип Sample with ConsoleOutput
имеет метод output
для типа Object
и метод doSomething
для типа Sample
. Поэтому он несет ответственность за обеспечение реализации обоих этих методов. Тот факт, что реализация output
находится в ConsoleOuput
, не имеет отношения к типу и, следовательно, не имеет отношения к тому, кто за него отвечает.
Объект Sample with ConsoleOutput
может легко переопределить реализацию output
, и в этом случае он будет явно отвечать за этот метод, а не ConsoleOutput
. Тот факт, что Sample with ConsoleOutput
решает не изменять реализацию output
, не означает, что он не несет за это ответственности. Обязанности объекта не меняются при изменении реализации.
Этот принцип является первым из пяти SOLID принципов разработки программного обеспечения.
Как объясняет Википедия: «Принцип единой ответственности [] гласит, что каждый модуль или класс должен нести ответственность за одну часть функциональности, предоставляемой программным обеспечением, и что ответственность должна быть полностью заключена в класс».
Другими словами, не делайте этого:
class MultipleResponsibilities {
def computePi(places: Int): List[Int]
def countVowels(text: String): Int
}
но сделайте это вместо:
class PiComputer {
def computePi(places: Int): List[Int]
}
class VowelCounter {
def countVowels(text: String): Int
}
computePi
и countVowels
являются различными частями функциональности программы, и поэтому они должны быть заключены в разные классы.
Третий принцип SOLID - это принцип подстановки Лискова , который гласит, что функциональность объекта должна зависеть исключительно от типа и не должна зависеть от реализации. Вы должны иметь возможность изменить реализацию и по-прежнему использовать объект таким же образом с теми же результатами.
Поскольку функциональность объекта полностью определяется типом объекта, обязанности объекта также полностью определяются типом. Изменение реализации не меняет обязанностей.