2015-02-18 4 views
0

скажем, что у меня есть несколько подклассов Creature, и каждый из них имеет какой-то метод getGroup(), который возвращает List<Creature>.Java: Как написать общий метод?

Что я могу сказать по «что-то вроде».getGroup() Метод заключается в том, что имя этой функции варьируется между подклассами. Например, Wolf s путешествуют в пакетах, поэтому у них есть член getPack(). Fish путешествия в школах, поэтому у них есть член .getSchool(), Humans есть член getFamily() и т. Д.

.getGroup() не существует в Creature, и его нельзя добавить в интерфейс. Ни один из этих разделов не может быть отредактирован.

Я пишу метод для печати числа Creature s в своей группе. Как мне это сделать?

По существу, я ищу, чтобы уплотнить эти две функции в одно и то же:

public void PrintSchoolSize(Fish dory) { 
     System.out.print(dory.getSchool().size()); 
    } 

    public void PrintHiveSize(Bee bee) { 
     System.out.print(bee.getColony().size()); 
    } 

... в следующей функции:

public void printGroupSize(Class<? extends Creature> cree, 
           FunctionThatReturnsList getGroup()) { 
     System.out.print(cree.getGroup().size(); 
    } 

Я предположил бы, что мне нужно пройти во втором аргументе (указатель функции?) до void printGroupSize. Любая помощь очень ценится, спасибо!

EDIT Спасибо всем за помощь. Это просто упрощение проблемы real, которую я пытаюсь решить. Длинные, слишком сложные проблемы сложнее ответить, поэтому я поставил этот более простой сценарий.

Единственный ответ заключается в использовании общей функции (если она существует). В классах, на которых я фактически работаю, нет общего интерфейса, но у всех есть функция, которая возвращает список.

+4

Вы должны сделать способ в «Существо», который они все переопределяют. – immibis

+0

'.getGroup() не существует в Существо, и его нельзя добавить в интерфейс' почему? Тогда что такое * * интерфейс? – EpicPandaForce

+0

Спасибо за помощь. К сожалению для меня, @Override не вариант. Вопрос, который я задал, - это просто упрощенное упрощение большей проблемы, которую я пытаюсь решить. Наиболее оптимальное решение основывается на общих функциях –

ответ

0

Спасибо всем за помощь. Поскольку я не разрешено редактировать любого из вышеупомянутых классов/интерфейсов (я могу писать только внешние функции), я написал следующую функцию

public List<? extends Creature> getGroup(Object obj) { 

     if(obj.getClass() == Bee.class) 
      return ((Bee)obj).getColony(); 

     if(obj.getClass() == Fish.class) 
      return ((Fish) obj).getSchool(); 

     /* repeat for the other classes */ 

     return null; 
    } 

... и использовать его здесь, как так:

public void printGroupSize(Class<? extends Creature> cree) { 
     System.out.print(getGroup(cree).size()); 
    } 

Я проверил, что это решение действительно работает, так как все функции получить *****() возвращает List<Creature>. Это решение также значительно сокращает мою кодовую базу и упрощается, чем текущая структура.

3

То, что вы описали в своем вопросе, мало связано с пониманием «общих методов» Java. Вы можете реализовать его с отражением (см. Class.getMethod()), но я обещаю вам, что вы действительно не хотите туда идти.

Было бы лучше, если бы Creature объявить способ abstractgetGroup(), что каждый подкласс будет отменен. Вы можете сделать это в дополнение к предоставлению методов с именами подкласса, если хотите. Код, который хочет получить группу (или ее размер), не зная определенного типа существа, будет ссылаться на метод этого существа getGroup(). Это приложение полиморфизма, который, кажется, то, что вы на самом деле после.

+0

Спасибо за подсказку. Я рассмотрю Class.getMethod(), поскольку это похоже на решение, которое я действительно ищу. –

+0

@JayFrizzle, как пожелаете. Я упомянул 'Class.getMethod()', потому что это действительно соответствует тому, что вы * задали *, но я должен повторить, что рефлексивное решение, включающее этот метод, вряд ли будет тем, что вы хотите *. Я призываю вас вместо этого перейти к лучшему дизайну. –

0

Если getGroup не может быть добавлен в интерфейс Существа, почему бы не добавить еще один интерфейс к вашим существам?

public interface HasGroup { 
    Group getGroup(); 
} 

означать, что вы можете создать метод:

public void printGroupSize(HasGroup cree) { 
    System.out.print(cree.getGroup().size(); 
} 
0

Самый простой способ это был getGroup() метод к интерфейсу Creature и реализовать его в каждом подклассе, но мне кажется, вы не можете сделать это.

Если вы можете изменить подклассы, я бы создал новый интерфейс CreatureGroupable с getGroupSize() и/или getGroup(). Каждый подкласс Creature должен реализовать этот интерфейс, например.

public interface CreatureGroupable { 
    CreatureGroup getGroup(); 
} 

public enum CreatureGroup { 
    WOLF_PACK("pack", 30), 
    GEES_FLOCK("flock", 20), 
    FISH_SCHOOL("school", 1000), 
    HUMAN_FAMILY("family", 4), 
    ... 
    private final String name; 
    private final int size; 

    private CreatureGroup(String name, int size) { 
    this.name = name; 
    this.size = size; 
    } 

    public String getName() { return name; } 
    public int getSize() { return size; } 
} 

public class Wolf implements Creature, CreatureGroupable { 
    // methods from Creature, constructor, ... 

    public CreatureGroup getGroup() { 
     return CreatureGroup.WOLF_PACK; 
} 

Таким образом, если у вас есть List<Creature> вы можете получить доступ к группе каждого из них и делать все, что вы должны сделать, например,

public void printGroups(List<Creature> creatures) { 
    for (Creature c : creatures) { 
     CreatureGroup group = c.getGroup(); 
     System.out.println("A " + group.getName() + 
         " has roughly " group.getSize() + 
         " individuals.");  
    } 
} 

Если вы хотите больше гибкости, вы не можете использовать enum и только стандартный interface и class иерархию групп.

Смежные вопросы