Java: «Перегрузка классов» - PullRequest
3 голосов
/ 17 февраля 2012

Хорошо, допустим, у меня есть файл класса с именем Orange, а затем два отдельных файла классов с именем Color и Fruit.

Внутри Orange есть некоторые свойства для цвета, размера, спелости и т. Д., Иметод setSize (int size).

Внутри Fruit есть некоторые свойства для имени, типа фрукта, есть ли у него семена, откуда он был импортирован и т. д., а затем методы setName (String name).), eat (), wash () и give (Person person).

Внутри Color есть некоторые свойства для имени, значений RGB, значений Hex, значений Alpha и т. д., а затем методы setName (), setAlpha(int alpha), setRGB (int r, int g, int b) и setHex (int hex).

Большая часть вышеупомянутой информации не имеет значения и предназначена только для того, чтобы помочь вам понять.В файле Orange Class есть объект, который называется «Родитель».Что мне нужно знать, так это то, можно ли для объекта «Родитель» установить фрукт или цвет?Позже в файле основного класса наступает момент, когда происходит myOrange.Parent.setName ("Bob"), и в обоих случаях (независимо от того, является ли Parent фруктом или цветом), это будет возможно, поскольку у Fruit есть метод setNameи Color тоже.

Спасибо

Ответы [ 7 ]

7 голосов
/ 17 февраля 2012

Тип Inheritance («перегрузка класса»?) Представляет отношение «is-a».Апельсин - это фрукт.Никаких дополнительных переменных не требуется;унаследованные члены доступны через this.

Композиция представляет собой отношение has-a.Апельсин имеет цвет.При использовании этого шаблона объявляется отдельная переменная, так что это явно то, что используется для Parent.

Таким образом, Parent (ужасно названная переменная) является экземпляром Color.

1 голос
/ 17 февраля 2012

В статически типизированном языке, таком как Java, вы не можете вызывать метод для переменной, , если только тип переменной не объявляет указанный метод .Тип переменной ограничивает ваш доступ к объектам, на которые указывает переменная;это как окно, которое позволяет вам видеть только часть объекта позади него.

Это отличается от языков с динамической типизацией;там тип переменной не ограничивает доступ к объекту.Пока у объекта есть метод, который вы вызываете, вы можете идти.

Так что в Java вам нужно:

  1. создать новый тип, который объявляет setNameметод.Самый гибкий способ сделать это - создать interface.Затем вы
  2. объявляете "implement" этот интерфейс в классах, которые на самом деле имеют метод setName, и
  3. используете созданный вами интерфейс для объявления переменной parent.

Например:

interface Nameable { void setName(String name); }

class Color implements Nameable {
    public void setName(String name) { }
    /* implement other Color methods */
}

class Fruit implements Nameable { 
    public void setName(String name) { } 
    /* implement other Fruit methods */ 
}

class Orange { Nameable parent; /* call parent.setName at some point */ }
1 голос
/ 17 февраля 2012

Если у Orange действительно есть родительский объект через наследование, он уже должен иметь доступ к своим функциям-членам.Похоже, вы пытаетесь заставить Orange наследовать и Color, и Fruit одновременно через обходной путь, потому что Java не поддерживает множественное наследование.Это, вероятно, не то, что вы действительно хотите сделать.Лучше всего установить правильные отношения, на которые уже намекали.

public class Color{methods}
public class Fruit{methods}
public class Orange extends Fruit
{
  private Color orangeColor;
  //Other member variables and functions.
}

Таким образом, Апельсин - это Фрукт, а имеет - Цвет.Если вы хотите, чтобы у Orange была способность БЫТЬ либо фруктом, либо цветом, вам нужно переосмыслить то, что вы хотите.Всегда можно иметь Fruit с name = "Orange" и Color с name = "Orange", фактически не делая их одного класса.

1 голос
/ 17 февраля 2012

Что вы, возможно, захотите сделать - это заставить Color и Orange реализовать интерфейс с именем «NameHolder» (если вы хотите выставить и метод получения, и метод установки) или «NameSetter» (если вы просто хотите выставить метод установки).

Вот так (я буду использовать NameHolder в качестве наиболее распространенного случая):

interface NameHolder {
String getName();
void setName(String name);
}

class Color implements NameHolder {
// methods and fields, setter and getter implemented
}

class Fruit implements NameHolder {
// methods and fields, setter and getter implemented
}

Таким образом, Orange может содержать свой «родительский» объект не как объект (который имеет очень мало поведения), а как экземпляр NameHolder. Это делает линию, которую вы указали:

private NameHolder Parent;
myOrange.Parent.setName("Bob");

Эта строка будет скомпилирована без ошибок (конечно, это приведет к исключению NullPointerException во время выполнения, если Parent равен нулю). Я также должен отметить, что руководящие принципы Java по кодированию рекомендуют, чтобы поля были строчными, поэтому это должно быть в соответствии с соглашением:

private NameHolder parent; 
myOrange.parent.setName("Bob");
1 голос
/ 17 февраля 2012

Если под "parent" вы подразумеваете "inherits from", то ответ - нет.Orange может наследоваться от Fruit, но не от Color.Наследование должно быть отношениями "есть".

Orange "is-a" Fruit, это правильно.

Orange "is-a" Color мммм звучит неправильно.

1 голос
/ 17 февраля 2012

Это действительно зависит от вашего варианта использования.Если класс «Orange» представляет оранжевый цвет, то для него может иметь смысл наследовать от класса «Color».Если он представляет фрукт, то, возможно, имеет смысл наследовать от класса "Fruit".

Однако ни в одном случае (по крайней мере, с учетом предоставленной информации) я не вижу причины для класса "Orange"иметь "родительскую" ссылку.Было бы более разумно (опять же, в зависимости от вашего варианта использования), чтобы ваш класс "Orange" расширял либо Color, либо Fruit, как я уже говорил.

0 голосов
/ 17 февраля 2012

Если вы хотите запрограммировать его таким образом, перед выполнением метода вы можете проверить, ссылается ли «Parent» на экземпляр Fruit или Color, а затем выполнить соответствующий вызов метода.

...