Наследование Java - моделирование нескольких объектов

1

У меня вопрос на Java, который может быть связан с множественным наследованием.

"Уокер" - человек, который может ходить и разводить, "Говорящий" - это человек, который может говорить и разводить, "Пловцом" является человек, который умеет плавать, разговаривать, ходить и размножаться.

Каков наилучший способ их моделирования на Java?

Спасибо за ваши ответы, Tejo

Теги:
inheritance

5 ответов

2

Вы должны извлечь поведение в интерфейсы, а не отдельные классы.

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 и т.д. и т.д.

  • 0
    +1 это путь (и «-able» соглашение об именах намного менее суровое и более традиционное, чем «I *», с которым я пошел).
  • 2
    @JasonC: Я считаю, что Java предпочитает -able, в то время как C # предпочитает I *. Оба языка достаточно схожи для меня, чтобы не создавать проблем в любом случае :)
Показать ещё 1 комментарий
1

"Уокер" - человек, который может ходить и разводить, "Говорящий" - это человек, который может говорить и разводить, "Пловцом" является человек, который умеет плавать, разговаривать, ходить и размножаться.

Я бы использовал интерфейсы для представления признаков и использовал конкретные классы для представления типов, например:

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* для интерфейсов; но я выбрал их уникальными, учитывая выбор слов.

  • 0
    Как было бы, если бы мы удалили интерфейс IBreeder и поместили метод breed() в базовый класс Person . Это будет хорошо?
  • 1
    Здесь у вас есть несколько реализаций одного и того же метода в более чем одном классе. Порода должна быть одинаковой для всех классов. Точно так же и ходить и разговаривать.
Показать ещё 2 комментария
1

Я вижу интерфейс как что-то, что удерживает 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

    }
  • 0
    Вы не хотели бы, чтобы Swimmable продлил Walkable или Talkable . Что если вам нужно определить человека, который умеет плавать, но не разговаривать? Что если вы хотите, чтобы Swimmer больше не мог ходить? Наличие Swimmable расширяет эти интерфейсы, что затрудняет внесение этих изменений без большого количества побочных эффектов (то же самое касается расширения Breedable ). Это значительно облегчило бы вещи только что Swimmer реализации Walkable , Talkable , Breedable и Swimmable .
  • 0
    Я полностью куплю вашу точку зрения и исправлю свою ошибку,
0

Я думаю, что вы должны иметь что-то подобное.

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

Но то, что вы действительно должны делать, это думать о разделении проблем. Достаточно ли общих точек между каждым из этих объектов для использования наследования? Возможно, нет.

  • 0
    Если вы сделаете это таким образом, вам будет очень трудно реализовать метод где-нибудь, скажем, безразлично, с каким типом человека он работает, пока он может говорить.
-2
class person{
 //breed function
 }
 class walker extends person{
 //walk function
 }
 class talker extends person{
 //talk function
 }
class swimmer extends talker{     
//swim function
//walk function
}
  • 0
    Если вы сделаете это таким образом, вам будет очень трудно реализовать метод где-нибудь, скажем, безразлично, с каким типом человека он работает, пока он может говорить.
  • 0
    Да, я думаю, что это неправильно в этом смысле. Спасибо
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню