Понимание классов - PullRequest
       19

Понимание классов

3 голосов
/ 21 июля 2009

Я новичок в программировании и у меня есть несколько вопросов о классах.

Я буду использовать Карел в качестве примера:

public class Karel extends robot{
   ....

}

тогда я расширяю Карел:

public class SuperKarel extends Karel{
   ....

}

но тогда я хочу организовать несколько групп методов:

public class KarelJumps extends SuperKarel {
    ....

}

public class KarelColor extends SuperKarel {
    ....

}

Но тогда, если я хочу заставить Карела прыгнуть, мне нужно создать экземпляр KarelJumps скорее SuperKarel. Но потому что KarelJumps является другой объект тогда KarelColor Я не мог использовать ни один из его методов.

Так что я бы просто положил все методы KarelJumps и KarelColor внутри SuperKarel? Я просто делаю один большой предмет?

Ответы [ 6 ]

4 голосов
/ 21 июля 2009

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

Вы хотите использовать эти методы, чтобы сделать ваши приложения менее сложными, а не более того. Для начинающего программиста я бы порекомендовал вам взять книгу «Код завершен» и на некоторое время сделать ее своей Библией. Вы не будете изучать язык сам по себе, но вы узнаете, как все должно быть сделано и почему это так.

2 голосов
/ 21 июля 2009

Похоже, вы пытаетесь понять полиморфизм больше, чем классы.

Наследование не обеспечивает механизм "группировки методов".

Основная концепция классического наследования и полиморфизма удобно отражена в Принципе замены Лискова . Украдено с этой вики-страницы:

если S является подтипом T, то объекты типа T в программе могут быть заменены объектами типа S без изменения каких-либо желательных свойств этой программы.

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

1 голос
/ 21 июля 2009

Я думаю, вы упускаете из виду концепцию методов. Классы - это структуры, которые могут содержать данные и определять методы. Чтобы выполнить действие, вам не нужно продолжать расширять исходный класс, вы можете определить новые методы. Расширение Karel - это хорошо, если есть причина, по которой вам нужно сделать в SuperKarel что-то похожее, но отличное от того, что делает Karel.

public class Karel extends robot{
    public void jump(){
    ...
    } 

   public void setColor(Color c) {
   ...
   }

}

public class SuperKarel extends Karel{
    public void jump(){
       //jump in a super way    
    } 

   public void setColor(Color c) {
       //set some super color 
   }
}
1 голос
/ 21 июля 2009

Если вам нужен Karel, который переходит и имеет доступ к KarelColor методам, вам нужно поместить их в один класс или изменить иерархию.

KarelJumps и KarelColor являются братьями и сестрами и не могут получить доступ к методам друг друга. Если вы действительно хотите хранить их отдельно, возможно:

public class SuperKarel extends Karel
public class KarelJumps extends SuperKarel
public class KarelColor extends KarelJumps

РЕДАКТИРОВАТЬ: Послушайте ответ ChrisB, хотя. Если вы не добавляете значительную функциональность для каждого расширяющего класса, вам, вероятно, следует избегать иерархии.

0 голосов
/ 21 июля 2009

Есть несколько решений:

  1. Вы можете переместить методы вверх в дереве классов (как вы уже знаете).

  2. Вы можете использовать интерфейс для объявления общих методов. Если KarelJumps и KarelColor реализуют интерфейс, некоторый код может запросить «реализацию этого интерфейса». Поскольку оба класса реализуют (удовлетворяют) интерфейс, код будет работать. Недостаток: Вы должны реализовать методы для интерфейса в каждом классе (дублирование кода -> плохо).

  3. Java не поддерживает «миксины», так что это не вариант, а для полноты: миксины - это фрагменты кода, которые компилятор копирует для вас. Таким образом, вы получаете единственное место, где вы можете поддерживать код, а затем сделать так, чтобы компилятор скопировал указанный код в тысячи мест (или использовать любой другой прием, чтобы он выглядел так, как он).

  4. Вы можете использовать делегата. Затем делегат реализует метод. В двух классах Karel вы добавляете поле delegate и вызываете реализацию делегата:

    interface IDelegate { void method (); }
    class Delegate implements IDelegate {
        void method () { ... }
    }
    
    public class KarelJumps extends SuperKarel implements IDelegate {
        IDelegate delegate = new Delegate ();
    
        // Instead of copying the code, delegate the work
        void method () { delegate.method (); }
    }
    
0 голосов
/ 21 июля 2009

Всякий раз, когда вы создаете класс, спрашиваете "что он делает?" Методы идут в классе.

Вы должны смотреть в первую очередь с точки зрения человека , используя ваш Карел.

Here is myK he is a Karel

oh, I wonder what he can do ... hmmm looks like a Karel can jump

myK.jump(howHigh)

hey he jumped

wonder what else he can do ...

Чего этот человек не хочет, так это множества различных объектов myK, mySuperK, myColouredK для выполнения различных работ. Вы даете ему хороший связный и полный объект Карел.

Если вы чувствуете, что это приводит к очень большому классу "Karel", и вам нужна дополнительная организация, вы можете разложить реализацию Karel (например, колеса, ручки и т. Д.) Для выполнения различных задач, но снаружи это Karel. .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...