Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Создание функции для нескольких типов параметра 
V
    Опции темы
nc30
Дата 6.9.2010, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Интересующийся :)
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 24.6.2010
Где: Санкт-Петербург

Репутация: 5
Всего: 8



Есть система классов:
Код

public class Person

public class Adult extends Person

public class ServiceClient extends Adult

Объекты этих классов обрабатывают специальные службы. Каждая работает на своем уровне (от Person до ServiceClient), но ряд действий одинаков: - записать объект в файл; - считать из файла список объектов и вернуть ссылку; - найти объект в файле и вернуть ссылку и т. п. Для этих нужд службам доступен класс Common  с соответствующим набором статических методов.

Первый вопрос: Как избежать вот такого:
Код

// В каждом файле хранится LinkedList<> объектов.
// "..." - одинаковый код.
public static void saveSomeoneToFile(Person toSave, String fileName) {
    List<Person> list = new LinkedList<Person>();
    ...
}

public static void saveSomeoneToFile(Adult toSave, String fileName) {
    List<Adult> list = new LinkedList<Adult>();
    ...
}

public static void saveSomeoneToFile(ServiceClient toSave, String fileName) {
    List<ServiceClient> list = new LinkedList<ServiceClient>();
    ...
}

Второй вопрос: Можно ли создать функцию, возвращающую <? extends Person> в зависимости от типа прочитанного из файла объекта?
Вариант с коллекцией проходит, если использовать вызов с явным приведением:
Код

    public static List<? extends Person> loadListOfSomeoneFromFile(String fileName) {
        List<? extends Person> list = null;
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(fileName));
            list = (List) ois.readObject();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                ois.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        return list;
    }

А если нужно вернуть ссылку не на коллекцию, а на ее элемент?

Пытался что-то делать с использованием Class, но как-то все наугад: опыта нет совсем  smile 
PM MAIL   Вверх
powerOn
Дата 6.9.2010, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(nc30 @  6.9.2010,  18:14 Найти цитируемый пост)
Первый вопрос: Как избежать вот такого:


Перенести метод saveSomeoneToFile в классы Person, Adult, ServiceClient и сделать его нестатическим.


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
nc30
Дата 6.9.2010, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Интересующийся :)
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 24.6.2010
Где: Санкт-Петербург

Репутация: 5
Всего: 8



Цитата(powerOn @ 6.9.2010,  15:30)
Перенести метод saveSomeoneToFile в классы Person, Adult, ServiceClient и сделать его нестатическим.

Дело в том, что ни один из этих классов не знает, как его объекты будут обрабатываться. По условию задачи, они вполне могут находиться в составе подключаемой сторонней библиотеки.

Наверное, можно включить данные методы в состав служебных классов (паспортный стол, ОЗАГС, отдел соцзащиты), которые обрабатывают объекты Person/Adult/ServiceClient. Но тогда получится, примерно, следующее:
Код

public class PassportService {
...
    public void saveSomeoneToFile(Adult toSave, String fileName) {
        List<Adult> list = new LinkedList<Adult>();
        ...
    }

    public void printListOfSomeoneFromFile(String fileName) {
        List<Adult> list = new LinkedList<Adult>();
        ...
    }

    public List<Adult> loadListOfSomeoneFromFile(String fileName) {
        List<Adult> list = new LinkedList<Adult>();
        ...
    }

    public Adult findSomeoneInFile(String fileName, int id) {
        ...
    }

}

public class RegistryOfficeService {
...
    public void saveSomeoneToFile(ServiceClient toSave, String fileName) {
        List<ServiceClient> list = new LinkedList<ServiceClient>();
        ...
    }

    public void printListOfSomeoneFromFile(String fileName) {
        List<ServiceClient> list = new LinkedList<ServiceClient>();
        ...
    }

    public List<ServiceClient> loadListOfSomeoneFromFile(String fileName) {
        List<ServiceClient> list = new LinkedList<ServiceClient>();
        ...
    }

    public ServiceClient findSomeoneInFile(String fileName, int id) {
        ...
    }

}

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

Есть ли возможность более универсально подойти к решению данной задачи?
PM MAIL   Вверх
aleksandy
Дата 7.9.2010, 05:20 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 260
Регистрация: 17.12.2006

Репутация: 4
Всего: 5



Цитата(nc30 @  6.9.2010,  17:14 Найти цитируемый пост)
А если нужно вернуть ссылку не на коллекцию, а на ее элемент?

Оно, или я не понял задачи?
Код
public static <T extends Person> T loadListOfSomeoneFromFile(String fileName, int index) {
    List<T> result = null;
    ObjectInputStream ois = null;
    try {
        ois = new ObjectInputStream(new FileInputStream(fileName));
        result = (List<T>) ois.readObject();
    } catch (ClassNotFoundException ex) {
        ex.printStackTrace();
    } catch (IOException ex) {
        ex.printStackTrace();
    } finally {
        try {
            ois.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    return result.get(index);
}



PM   Вверх
nc30
Дата 7.9.2010, 07:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Интересующийся :)
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 24.6.2010
Где: Санкт-Петербург

Репутация: 5
Всего: 8



Цитата(aleksandy @ 7.9.2010,  03:20)
Оно, или я не понял задачи?

Да, то что нужно, спасибо. Второй вопрос решен  smile 

Остался первый. Есть возможность сделать подобное для параметра функции? Что-то вроде:
Код
    
    // как это исправить?
    public static void saveSomeoneToFile(<T extends Person> T someoneToSave, String targetFileName) {
        List<T> list = new LinkedList<T>();

        ObjectOutputStream oos = null;
        try {
            File targetFile = new File(targetFileName);

            if (targetFile.exists() && targetFile.isFile()) {
                ObjectInputStream ois = null;

                try {
                    ois = new ObjectInputStream(new FileInputStream(targetFileName));
                    try {

                        list = (List) ois.readObject();

                    } catch (ClassNotFoundException ex) {
                        ex.printStackTrace();
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                try {
                    targetFile.createNewFile();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }

            list.add(someoneToSave);
            oos = new ObjectOutputStream(new FileOutputStream(targetFileName));
            oos.writeObject(list);

        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                oos.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

Т. е., чтобы один метод подходил для всех наследников Person.

И еще. Посоветуйте, пож-та, где можно про эти механизмы почитать более подробно?
PM MAIL   Вверх
ivanovpv
Дата 7.9.2010, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



А почему нельзя передавать тип родителя в параметрах, а в теле функции распознавать точный тип?
Код

public static void saveSomeoneToFile(Person toSave, String fileName) 
{
    if(toSave instanceof ServiceClient)
        ...
    else if(toSave instanceof Adult)
        ...
    else 
       ...
}




--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
powerOn
Дата 7.9.2010, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



Цитата(ivanovpv @  7.9.2010,  10:52 Найти цитируемый пост)
А почему нельзя передавать тип родителя в параметрах, а в теле функции распознавать точный тип?


Потому, что добавление нового наследника от Person потребует модификации кода метода saveSomeoneToFile, а не его расширения. Это нарушение Open Close Principle проектирования.


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
aleksandy
Дата 7.9.2010, 13:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 260
Регистрация: 17.12.2006

Репутация: 4
Всего: 5



Код

 public static <T extends Person> void saveSomeoneToFile(T someoneToSave, String targetFileName)

PM   Вверх
nc30
Дата 7.9.2010, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Интересующийся :)
*


Профиль
Группа: Участник
Сообщений: 140
Регистрация: 24.6.2010
Где: Санкт-Петербург

Репутация: 5
Всего: 8



Цитата(aleksandy @ 7.9.2010,  11:28)
Код

 public static <T extends Person> void saveSomeoneToFile(T someoneToSave, String targetFileName)

Спасибо за помощь. Заработало  smile 

Немного подумав, я по этому же принципу переписал уже работающую функцию:
Код

    public static List<? extends Person> loadListOfSomeoneFromFile(String fileName) {
        List<? extends Person> list = null;
        ...
на
Код

    public static <T extends Person> List<T> loadListOfSomeoneFromFile(String fileName) {
        List<T> list = null;
        ...

Стало более красиво.

Это сообщение отредактировал(а) nc30 - 7.9.2010, 14:03
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0555 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.