2009-07-21 2 views
3

Я новичок в программировании и задаю некоторые вопросы о классах.Понимание классов

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

public class Karel extends robot{ 
    .... 

} 

я продлить Карел:

public class SuperKarel extends Karel{ 
    .... 

} 

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

public class KarelJumps extends SuperKarel { 
    .... 

} 

public class KarelColor extends SuperKarel { 
    .... 

} 

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

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

ответ

4

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

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

1

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

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

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

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

1

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

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 
    } 
} 
0

Всякий раз, когда вы создаете класс, спросите: «Что он делает?» Методы идут в классе.

Вам необходимо смотреть в первую очередь с точки зрения человека используя ваш Karel.

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 (подумайте, колеса, ручки и т. Д.), Чтобы выполнять различные задачи, но со стороны это Карелы.

2

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

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

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

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

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

0

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

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

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

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

  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(); } 
    } 
    
Смежные вопросы