2015-03-03 5 views
0

Если у меня есть класс «Собака», который расширяет класс «Животные», а класс «Животное» имеет конструктор с несколькими атрибутами типа latinName, latinFamily и т. Д. Как мне создать конструктор для собаки? Должен ли я включать все атрибуты, которые содержатся в животных, а также все дополнительные атрибуты, которые я хочу в Собаке, как так:Конструктор подкласса с дополнительными атрибутами

public Animal(String latinName){ 
    this.latinName = latinName; 
} 

public Dog(String latinName, breed){ 
    super(latinName); 
    this.breed = breed; 
} 

Фактические классы имеют гораздо больше атрибутов, чем я перечислил здесь, для этого конструктор для собаки становится довольно длинным, и я сомневаюсь, что это был путь, или если есть более аккуратный способ?

+0

Да, это способ продолжения. Вы можете инкапсулировать параметры на карте или в класс обертки для удобства чтения, если хотите. –

+0

Вы правы, включите все атрибуты, найденные в Animal, и все дополнительные атрибуты, которые вы хотите в классе Dog. Просто исправьте свой код с типом данных в параметрах. как 'public Dog (String latinName, порожденная DataTypeOfBreed)' –

ответ

2

Должен ли я включать в себя все атрибуты, которые содержатся в животных ...

Те, которые не являются инвариантными для собак, да (так или иначе, см. Ниже) Но, например, если у Animal есть latinFamily, тогда вам не нужно Dog, так как это всегда будет "Canidae". Например:

public Animal(String latinFamily){ 
    this.latinFamily = latinFamily; 
} 

public Dog(String breed){ 
    super("Canidae"); 
    this.breed = breed; 
} 

Если вы найти количество аргументов конструктору быть unweildy, вы могли бы рассмотреть шаблон Builder:

public class Dog { 

    public Dog(String a, String b, String c) { 
     super("Canidae"); 
     // ... 
    } 

    public static class Builder { 
     private String a; 
     private String b; 
     private String c; 

     public Builder() { 
      this.a = null; 
      this.b = null; 
      this.c = null; 
     } 

     public Builder withA(String a) { 
      this.a = a; 
      return this; 
     } 

     public Builder withB(String b) { 
      this.b = b; 
      return this; 
     } 

     public Builder withC(String c) { 
      this.c = c; 
      return this; 
     } 

     public Dog build() { 
      if (this.a == null || this.b == null || this.c == null) { 
       throw new InvalidStateException(); 
      } 

      return new Dog(this.a, this.b, this.c); 
     } 
    } 
} 

Использование:

Dog dog = Dog.Builder() 
      .withA("value for a") 
      .withB("value for b") 
      .withC("value for c") 
      .build(); 

Это делает легче понять, какой аргумент представляет собой, поскольку он противоположен длинной строке аргументов конструктору. Вы получаете преимущества ясности (вы знаете, что withA указывает «а» информацию, withB указывает «b» и т. Д.), Но без опасности создания полуразработанного экземпляра Dog (поскольку частично построенные экземпляры - плохая практика) ; Dog.Builder хранит информацию, а затем build выполняет работу по строительству Dog.

+1

Интересный шаблон построителя как альтернатива длинным спискам аргументов. – Juxhin

0

Если собака расширяет Животное, тогда да, вы бы хотели продолжить использование аргументов Животного (потому что собака действительно животное) и возможно добавьте больше, чтобы различать собаки и животные объекты.

Итак, в общем случае да, вам нужно будет включить все аргументы родительских классов.

Также рассмотрим возможность использования нескольких конструкторов с возможно более коротким списком аргументов. Скажите, что Animal принимает аргумент String type, который определяет тип животного, класс ребенка, вам не нужно передавать его каждый раз для Dog.

public Dog (String name){ 
    super("Dog", name); 
} 

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