У меня вопрос на Java, который может быть связан с множественным наследованием.
"Уокер" - человек, который может ходить и разводить, "Говорящий" - это человек, который может говорить и разводить, "Пловцом" является человек, который умеет плавать, разговаривать, ходить и размножаться.
Каков наилучший способ их моделирования на Java?
Спасибо за ваши ответы, Tejo
Вы должны извлечь поведение в интерфейсы, а не отдельные классы.
interface Swimmable{
void swim();
}
interface Talkable{
void talk();
}
interface Walkable{
void walk();
}
class Person {
void breed();
}
Обратите внимание, как я назвал их Walkable вместо Уокера. Это указывает на то, что этот интерфейс определяет поведение и не является автономным. Теперь ваш фактический объект можно назвать Уокер, но лексически говорящий walkable также имеет больше смысла, если вы используете его для других классов, которые хотят этого поведения.
Там много шумихи о "композиции над наследованием", но на самом деле это просто несоответствующее решение для программистов, использующих два взаимозаменяемых, когда им этого не нужно.
Теперь, если вы хотите создать объект, который может плавать и ходить, вы можете просто определить его как таковой:
class Athlete extends Person implements Swimmable, Walkable {
@Override
void swim(){ }
@Override
void walk(){ }
}
и не будет беспорядка с фактическими примерами поведения, которые должны будут быть вызваны через другой уровень в действительном классе Athlete
и т.д. и т.д.
"Уокер" - человек, который может ходить и разводить, "Говорящий" - это человек, который может говорить и разводить, "Пловцом" является человек, который умеет плавать, разговаривать, ходить и размножаться.
Я бы использовал интерфейсы для представления признаков и использовал конкретные классы для представления типов, например:
public interface IWalker {
public void walk ();
}
public interface IBreeder {
public void breed ();
}
public interface ITalker {
public void talk ();
}
public interface ISwimmer {
public void swim ();
}
public class Person {
}
public class Walker extends Person implements IWalker, IBreeder {
@Override public void walk () { ... }
@Override public void breed () { ... }
}
public class Talker extends Person implements ITalker, IBreeder {
@Override public void talk () { ... }
@Override public void breed () { ... }
}
public class Swimmer extends Person implements ISwimmer, ITalker, IWalker, IBreeder {
@Override public void swim () { ... }
@Override public void walk () { ... }
@Override public void talk () { ... }
@Override public void breed () { ... }
}
Таким образом, вы можете, скажем, использовать IWalker
повсюду, что ожидается что-либо, что может ходить, или Swimmer
любом месте, где ожидается определенный тип человека, или Person
любом случае, когда ожидается общий родительский человек.
Для записи мне не очень нравится схема именования I*
для интерфейсов; но я выбрал их уникальными, учитывая выбор слов.
IBreeder
и поместили метод breed()
в базовый класс Person
. Это будет хорошо?
Я вижу интерфейс как что-то, что удерживает ablity
которую имеет сущность, возможно, поэтому в JavaSE многие интерфейсы называются XXXable, где XXX обозначает способность, например Comparable
, Serializable и т.д.
Здесь, Breeading, Talking, Walking, Swimming - способность определенного человека. Таким образом, у организации есть некоторая хитрость. Поэтому я делаю все эти независимые способности, поскольку интерфейсы и сущности (Swimmer, Talker, Walker
) реализуют этот интерфейс, чтобы получить эти абляции.
interface Breedable {
public void breed();
}
interface Walkable {
public void walk();
}
interface Talkable {
public void talk();
}
interface Swimmable {
public void swim();
}
class Swimmer implements Swimmable, Walkable, Talkable, Breedable {
@Override
public void breed() {
// TODO Auto-generated method stub
}
@Override
public void talk() {
// TODO Auto-generated method stub
}
@Override
public void swim() {
// TODO Auto-generated method stub
}
@Override
public void walk() {
// TODO Auto-generated method stub
}
Swimmable
продлил Walkable
или Talkable
. Что если вам нужно определить человека, который умеет плавать, но не разговаривать? Что если вы хотите, чтобы Swimmer
больше не мог ходить? Наличие Swimmable
расширяет эти интерфейсы, что затрудняет внесение этих изменений без большого количества побочных эффектов (то же самое касается расширения Breedable
). Это значительно облегчило бы вещи только что Swimmer
реализации Walkable
, Talkable
, Breedable
и Swimmable
.
Я думаю, что вы должны иметь что-то подобное.
public class Person
//Breed method here
public class Walker extends Person
//Walk method here
public class Talker extends Person
//Talk method here
public class Swimmer extends Person
//Swim, talk & walk method here
Но то, что вы действительно должны делать, это думать о разделении проблем. Достаточно ли общих точек между каждым из этих объектов для использования наследования? Возможно, нет.
class person{
//breed function
}
class walker extends person{
//walk function
}
class talker extends person{
//talk function
}
class swimmer extends talker{
//swim function
//walk function
}