2010-09-26 3 views
1

Я недавно узнал, как 3 новых языка, и я начинаю их путать. Я не работал Java, делая что-то особенно сложное (вне android) через пару лет. У меня возникли проблемы с запоминанием, если это возможно:Изменение семантики методов подкласса в java

Я подклассифицирую ArrayList в основном, поэтому я могу сохранить приказ арраиста. Я пытаюсь переопределить метод add(object), но я хочу, чтобы он возвращал int вместо логического (местоположение добавляемого объекта). Но я получаю ошибки в возвращаемом типе моего метода.

Является ли то, что я хочу даже на языке? Можете ли вы, чтобы метод в подклассе возвращал нечто отличное от метода суперкласса?

Или я пытаюсь сделать что-то глупое? Разве это нарушает идею наследования is-a? Должен ли я просто инкапсулировать арраиста вместо его расширения?

Для справки, часть того, что я пытаюсь сделать:


public class AuthorArray extends ArrayList \{ 

    @Override 
    public int add(Author object) { 
     super.add(object); 

     Collections.sort(this, new SortByLastName()); 

     return this.indexOf(object); 
    } 
} 
+1

Я думаю, что с помощью 'ArrayList' не идеально подходит для этого. Попробуйте 'SortedSet', например:' TreeSet'. – NullUserException

ответ

3

Вы можете иметь метод в подклассе возвратного нечто иное, чем метод суперкласса?

В общем, нет. Единственным исключением является covariant return types, когда переопределенный метод возвращает подкласс возвращаемого типа в методе базового класса/интерфейса. Это стало возможным благодаря Java5, и это хорошая практика. Но ваше дело не относится к этой категории.

Является ли это нарушением идеи о наследовании?

Да. Пользователи ArrayList ожидают получить boolean возвращаемое значение от add и увидеть элементы в том же порядке, в каком они их добавили, и вы нарушите это ожидание. Не делай этого.

Должен ли я просто инкапсулировать арраиста вместо его расширения?

Да. Затем вы можете определить свой собственный интерфейс с любым контрактом, который вы предпочитаете. Но сначала рассмотрим вместо TreeSet вместо.

+0

Ах спасибо. По какой-то причине я не мог для жизни найти подходящий класс коллекций. Я не знаю, что моя проблема была – Falmarri

0

Интерфейс List гарантирует, что элементы будут возвращены в том же порядке, в котором они будут добавлены. Таким образом, если у вас есть только один поток, управляющий списком, вы можете легко выполнить добавление, а затем запросить его размер. size - 1 - порядковое значение элемента.

Если вышеуказанный заказ не является тем, что вы хотите, у вас есть два варианта: либо сортировать список, используя методы Collection.sort(), либо использовать SortedSet. Оба метода могут принимать компаратор.

Я никогда не видел необходимости расширять рамки коллекций Java и не рекомендую вам делать это в этом случае.

1

Смена семантики - это плохо. В вашем случае изменение имени метода от add до myadd устранит вашу проблему, если вы хотите просто исправить.

Лично я бы посоветовал узнать, как использовать Google guava-libraries неизменяемые, отсортированные структуры данных с помощью «функции», чтобы получить обзор обновлений, просмотреть youtube.

Но здесь, в стандартной Java, я сделал пример, как использовать TreeSet autosort - собственный класс, 2-мерный компаратор и эффективный эквивалент двоичного поиска.

public static class customC { 
    private String name; 
    private int value; 

    public customC(String name, int value) {super();this.name = name;this.value = value;} 
    public String getName() {return name;} 
    public void setName(String name) {this.name = name;} 
    public int getValue() {return value;} 
    public void setValue(int value) {this.value = value;} 

    @Override 
    public String toString() { 
     return new StringBuilder().append("[").append(this.name) 
       .append(":").append(this.value).append("]").toString(); 
    } 
} 

public static void main(String[] args) { 
    TreeSet<customC> ts = new TreeSet<customC>(new Comparator<customC>(){ 
     public int compare(customC a, customC b) { 
      int result = a.getName().compareToIgnoreCase(b.getName()); 
      return (result != 0 ? result : a.getValue() - b.getValue()); 
     } 
    }); 
    ts.add(new customC("ab", 1988)); 
    ts.add(new customC("ab", 1979)); 
    ts.add(new customC("ba", 1988)); 
    ts.add(new customC("ab", 1984)); 
    ts.add(new customC("ab", 1980)); 
    customC ce = new customC("ab", 1983); 
    ts.add(ce); 

    StringBuilder sb = new StringBuilder(); 
    sb.append(ts.headSet(ce).last()).append(" comes before ") 
     .append(ce).append("\n").append(ts); 

    System.out.println(sb.toString()); 
} 

Этот выход будет:

[ab:1980] comes before [ab:1983] 
[[ab:1979], [ab:1980], [ab:1983], [ab:1984], [ab:1988], [ba:1988]] 
Смежные вопросы