Обычная версия
Java форум JavaTalks
форум программистов

Поиск   Пользователи   Группы   Регистрация 
 Профиль   Личные сообщения 

 Вход 

Коллекция и разные типы.
Список форумов
 ->  Коллекции (Java Collection Framework)


 
Начать новую тему 
Предыдущая тема :: Следующая тема  
Автор Сообщение
matvey : 33
Новичок
Откуда: Novosibirsk

СообщениеМар 11, 2010 8:07 
Ответить с цитатой
Доброго времени суток!

Вкратце опишу ситуацию, что-то не могу сообразить:
Под рукой исходников нет, но попробую:

Есть примерно следующая иерархия классов:
Код:

class A {
  void meth1() {} // вообще у меня геттеры/сеттеры, но в данном  // случае это не принципиально
  void meth2() {}
  void meth3() {}
}
class B extends A {
  void methB1() {}
  void methB2() {} // ... и т. д.
}
class C extends B {
  void methC() {}
  void methC2() {}
}
class D extends B {
 /// ...
}


Есть основной класс, в котором любые созданные в иерархии объекты нужно хранить в коллекции, например в ArrayList-е:

Код:

class Main {
  public static void main(String args[]) {
    ArrayList list = new ArrayList();
    list.add(new C());
    list.add(new D());
    list.add(new A());
}
}


Я думаю, понятно, что просто хочу хранить в коллекции ссылку на любой объект из иерархии. Но вот как сделать так, чтобы пробегая по листу, например, вот так:
Код:

Iterator iter = list.iterator();
while (iter.hasNext()) {
iter.next();
}

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

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

class MyList<T> extends ArrayList<T> {
  T ob;
  MyList(T ob) { this.ob = ob; }

  void adding(T o) {
     add(o);
 }
 T getting() {

 } // в общем пробовал применить генерики - еще больше запутался.
}


Может существует какое - то более универсальное решение? Подскажите, как быть. Горю!
К началу Посмотреть профиль Отправить личное сообщение
Xcam : 155
Новичок

СообщениеМар 11, 2010 11:09 
Ответить с цитатой
Посмотрите в сторону приведения типов и оператора instanceof
К началу Посмотреть профиль Отправить личное сообщение
matvey : 33
Новичок
Откуда: Novosibirsk

СообщениеМар 11, 2010 12:10 
Ответить с цитатой
Блин, применял же уже, вылетело из головы. Спасибо! Получается, к помощи генериков можно не прибегать вообще?
К началу Посмотреть профиль Отправить личное сообщение
Jean : 1992
JavaTalks Team Member
Откуда: Санкт-Петербург

СообщениеМар 11, 2010 14:07 
Ответить с цитатой
Генерики могут помочь в приведении к наименьшему общему типу. В вашем случае это класс А. Но если классы C и D, например, имеют какой-то иной интерфейс (другие методы относительно А, то нужно будет явно приводить тип.
Опишите задачу, наверняка вы решаете ее не самым оптимальным методом.
_________________
Всякое решение плодит новые проблемы
К началу Посмотреть профиль Отправить личное сообщение
matvey : 33
Новичок
Откуда: Novosibirsk

СообщениеМар 11, 2010 18:10 
Ответить с цитатой
Задача - вывести в виде дерева на консоль объекты иерархии классов вместе с их свойствами. У меня магазин товаров, но я был бы рад, если бы рассмотрели на любом примере.
По условию задачи больше ничего не сказано, но слово "дерево" меня настораживает: а не придется ли использовать в качестве коллекции хранения не ArrayList а какой - нибудь TreeSet? В данный момент у меня все очень примитивно:
У каждого подкласса пару своих свойств, которые достаются и устанавливаются дополнительными геттерами и сеттерами, вроде больше ничего особеного. Самое сложное - вывод. Я пока не пойму, во-первых, стоит ли использовать TreeSet вместо ArrayList и как лучше вывести на консоль в виде именно дерева?

Классы в разных файлах, просто здесь приведу все вместе.

Код:

public interface MainInterface {
    public void setMyName(String name);
    public String getMyName();
    public void setPrice(Integer price);
    public Integer getPrice();
    public void setBarcode(Long code);
    public Long getBarcode(); // all setters and getters;
}


 */
public class Product implements MainInterface {
    protected String name; // название товара
    protected Integer price; // цена
    protected Long barcode; // штрих-код
    String thisName = this.getMyName();
    // ------------
    public Product() {
        this.setMyName("Books");       
    } // default constructor;
    public Product(String name, Integer price, Long barcode) {
        // set params:
        this.name = name;
        this.setMyName(name);
        this.price = price;
        this.barcode = barcode;
    } // constructor


    public void setMyName(String name) { this.name = name; };
    public void setPrice(Integer price) {};
    public void setBarcode(Long barcode) {};

    public String getMyName() { return name; };
    public Integer getPrice() { return price; };
    public Long getBarcode() { return barcode; };
}
class Book extends Product {
      private int PAGES; // page numbers;

    public Book() {} // default constructor;
    public Book(String name, Integer price, Long barcode) {       
        super(name, price, barcode);
    } // constructor;


    // то же самое и для сеттера:
    final void setPages(int PAGES) {
        this.PAGES = PAGES;
    }
    final int getPages() {
        return PAGES;
    } // getting pages;
}
class ProgrammersBook extends Book {
       private String language;
    public ProgrammersBook(String name, Integer price, Long barcode) {
        super(name, price, barcode);
    }

    public ProgrammersBook() {}

// get and set language;
    public String getLanguage() {
        return language;
    } // return language of programming;
    public void setLanguage(String language) {
        this.language = language;
    } // setting language;
}
class CookBook extends Book {
    private String[] ingredient;

    public CookBook(String name, Integer price, Long barcode) {
        super(name, price, barcode);
    }
      public String[] getIngradient() {
        return ingredient;
    } // return language of programming;
    public void setIngradient(String[] ingredient) {
        this.ingredient = ingredient;
    } // setting language;
}
class Esotericism extends Book {
        private int age;

    public Esotericism(String name, Integer price, Long barcode) {
        super(name, price, barcode);
    }
      public int getAge() {
        return age;
    } // return language of programming;
    public void setAge(int age) {
        this.age = age;
    } // setting language;
}



public class Main {
    private static ArrayList list = new ArrayList();
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        Product pr = new Product();
        list.add(new ProgrammersBook("Java2", 1200, 4353245345L));
        list.add(new ProgrammersBook("C++", 1300, 123121231145L));
        list.add(new CookBook("Receptes", 340, 123124435456L));
        list.add(new CookBook("Recepts 2", 340, 123124435456L));
        list.add(new Esotericism("Сафронов А.Г", 500, 1243234324234L));
       

        Iterator iter = list.iterator();
       // while cycle:
        while (iter.hasNext()) {
            Object ob = iter.next();
            // if - else instanceof:
            if (ob instanceof CookBook) {
                CookBook cb = (CookBook)ob;
                cb.getMyName();
                cb.getPages();
                cb.getPrice();
                cb.getIngradient();
            } else if (ob instanceof ProgrammersBook) {
                ProgrammersBook pb = (ProgrammersBook)ob;
                pb.getLanguage();
                pb.getMyName();
                pb.getPages();
                pb.getPrice();
               
            } else if (ob instanceof Esotericism) {
                Esotericism e = (Esotericism)ob;
                e.getAge();
                e.getMyName();
                e.getPages();
                e.getPrice();
            } // end if - else;
        }
       


    }

}




упростил все до примитивного, главное - понять суть. Так вот, как мне посоветовали выше, использовал instanceof. Будет ли это приемлемым решением? Или лучше поступить как-то по-другому?
Ну и как генерики использовать я тоже пока не пойму. Вот сейчас экспериментирую, но пока не выходит.
К началу Посмотреть профиль Отправить личное сообщение
Jean : 1992
JavaTalks Team Member
Откуда: Санкт-Петербург

СообщениеМар 11, 2010 20:58 
Ответить с цитатой
Каждый элемент должен отвечать за вывод себя сам. В вашем общем классе (или лучше интерфейсе) определите любой метод, который будет отвечать за вывод. Вполне подойдет и стандартный toString().
В ваш ArrayList (или что бы там ни было) кладите объекты именно этого общего класса (или интерфейса). Заранее известно, что у них будет метод для вывода.
Затем в цикле просто вызываете этот метод и у каждого объекта он отрабатывает по-своему: не нужны будут никакие приведения типов и проверок на instanceof. Это будет правильно.

Что означает вывести в виде дерева? С отступами? У вас элементы вложены один в другой, - например, объект класса А содержит объекты класса Б и т.д.?

ArrayList от TreeSet отличаются, но не так как вам бы хотелось - к дереву оба имеют посредственное отношение (особенно в плане вывода). Почитайте об этих коллекциях в той же "Философии Java".
_________________
Всякое решение плодит новые проблемы
К началу Посмотреть профиль Отправить личное сообщение
sx01 : 96
Новичок
Откуда: Санкт-Петербург

СообщениеМар 11, 2010 21:07 
Ответить с цитатой
Насолько я увидел в вашем примере вам необходимо хранить в коллекции экземпляры классов унаследованных от book, для этого вы можете использовать генерик, т.е.
Код:

private static ArrayList<Book> list = new ArrayList<Book>();

Далее при добавлении книги в этот лист будет автоматически проделано восходящее преобразование к классу Book, далее так в вашем классе хранятся только объекты иерархии Book вместо
Код:

while (iter.hasNext()){...}

вы можете использовать синтаксис
Код:

for(Book b: list){
b.get......
}

Если вам нужен просто вывод на консоль я бы корневой класс Book объявил абстрактным и объявил внем абстрактным метод toString(), тем самым обязывая всех наследников переопределять его и в нем возвращал бы строку со всеми парметрами объекта. Далее никакой instanceof использовать будет не обязательно, будет работать run-time полиморфизм, т.е. каждый раз будет вызываться метод toString() нужного класса.

TreeSet - это коллекция, которая хранит элементы в отсортированном порядке, в Set не может быть одинаковых элементов.
К началу Посмотреть профиль Отправить личное сообщение
matvey : 33
Новичок
Откуда: Novosibirsk

СообщениеМар 11, 2010 21:20 
Ответить с цитатой
Спасибо за ответы. Я правильно понял, что нужно заставить все классы переопределять метод toString() и вызывать в нем на вывод определенные в рамках данного класса методы, которые возвращают переменные соответствующего класса, необходимые для вывода?

Цитата:
Если вам нужен просто вывод на консоль я бы корневой класс Book объявил абстрактным и объявил внем абстрактным метод toString()

А если объявить все - таки в интерфейсе, это подойдет?

Цитата:
У вас элементы вложены один в другой, - например, объект класса А содержит объекты класса Б и т.д.?


нет, насколько мне понятно по задаче, имеет место быть только иерархия, но вложенность. например: книга - один класс, "книга по Java" или книга "поэзия Пушкина" два его наследника и т. д. - все унаследованные от Book, который в свою очередь унаследован от product. Последний класс создается на вершине иерархии, так как помимо книг есть и другие товары, получается он как бы определяет общую специфику для всех товаров.

PS Про TreeSet уже прочитал, понял, что не то совсем.
По поводу вывода на консоль - просто сказано: вывести полный список книгсо всеми свойствами.

Кстати, попутно возникло несколько вопросов:
- как лучше поступить с собственными переменными каждого класса: передавать их в конструктор, или устанавливать посредством методов?
- в каких классах будут нужны дефолтные конструкторы?
- может сеттеры в составе интерфейса убрать, раз я все равно все параметры передаю в конструктор для каждого класса?
К началу Посмотреть профиль Отправить личное сообщение
matvey : 33
Новичок
Откуда: Novosibirsk

СообщениеМар 12, 2010 10:54 
Ответить с цитатой
Цитата:
Что означает вывести в виде дерева? С отступами? У вас элементы вложены один в другой, - например, объект класса А содержит объекты класса Б и т.д.?


Маленькое уточнение... Здесь. если я правильно понял, скорее да, чем нет, однако, вопрос тогда остается. Как формировать отступы? Обычными табами? Да, получается вложенная иерархия.
К началу Посмотреть профиль Отправить личное сообщение
matvey : 33
Новичок
Откуда: Novosibirsk

СообщениеМар 17, 2010 16:47 
Ответить с цитатой
Можно ли как - то осуществить сортировку по объектам? Например, чтобы объекты одного типа хранились в самом "начале" коллекции, а других - "внизу" коллекции?
К началу Посмотреть профиль Отправить личное сообщение
Jean : 1992
JavaTalks Team Member
Откуда: Санкт-Петербург

СообщениеМар 17, 2010 22:10 
Ответить с цитатой
Можно. Для этого нужно реализовать интерфейс Comparator и использовать его. Для сортировки List можно вызвать это:
Код:
Collections.sort(list, YourComparator );

Для сортировки Set можно использовать TreeSet и компаратор отдать ему в конструктор.
_________________
Всякое решение плодит новые проблемы
К началу Посмотреть профиль Отправить личное сообщение
 
Начать новую тему  Ответить на тему
Страница 1 из 1
Список форумов
 -> Коллекции (Java Collection Framework)


 
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Java and all Java-related trademarks and logos are trademarks or registered trademarks of Oracle Corporation in the United States and other countries.
Это сайт не относится к фирме Oracle Corporation и не поддерживается ею.

© 2006-2010 www.javatalks.ru: форум java программистов
Используется скрипт phpBB © 2001, 2010 phpBB Group

Хостинг от bizname.ru