Список форумов forum.alsor.net forum.alsor.net
Форум небольшого круга друзей
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 

и так наследование...
На страницу Пред.  1, 2, 3, 4  След.
 
Начать новую тему   Ответить на тему    Список форумов forum.alsor.net -> IT-форум
Предыдущая тема :: Следующая тема  
Автор Сообщение
teg



Зарегистрирован: 20.12.2005
Сообщения: 410

СообщениеДобавлено: Сб Мар 07, 2009 1:02 am    Заголовок сообщения: Ответить с цитатой

И фсё? И драки не будет штоль?

getById, deleteById, insertById, updateById -- можно всё это сделать универсально и красиво. Можно написать базовый класс. И даже красиво можно отнаследоваться. Но есть ряд правил/проблем.

1. Нельзя расширять набор этих методов. Это обычно не соблюдается, потому что не удобно.
2. Это фсё будет имет смысл, если на самом деле не будет иерарахии. Т.е. если существует набор классов Кn, где n = 1,2,3...99 и для всех этих классов работает один DAO. И существует класс К100, для которого мы пишем DAO100, причём про это нихто не в курсе, потому чта мы работаем через базовый класс/интерфейс и экземпляр получаем через сервис-локатор.
Это правило не возможно соблюсти, нарушив (1).
3. Теперь проблема -- а что прикажете делать, когда нужен getByName? А этот самый name есть только у 50. Ну ес-но сабклассимся. А ещё у 50 есть uuid. Но только не вдоль, а поперёк.

Вот Лёха несколько раз заявил, что не существует универсального метода загрузить объект. Так вот, Лёха не прав. Методы существуют. Те из них, которые можно рассматривать всерьёз, будут использовать метаданные для этого. Т.е. не сотня классов, связанных в клубке странных наследований, а просто 100 различных дескрипторов. На примитивном уровне -- это просто 100 различных имён таблиц. Используя только такие метаданные, я ща набросаю универсальный загрузчег плоских объектов. Шобы грузить что-то посложнее метаднные и загрузчег придётся усложнить и возможно отсабкласить кого-то из них.

Мишк, можешь кратко объяснить, зачем тебе наследование? Если тебе того очень хочется, это одно. Но есть ли какие-то ещё причины?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Сб Мар 07, 2009 1:03 am    Заголовок сообщения: Ответить с цитатой

итак, потягивая пулайнер... продолжим.

Насчет генериков это я конечно сморозил - именно тут нам генерики помогут - как раз благодаря им мы избежим ручного написания ста классов не потеряв в типизации. И смотри, Мишка, что получается:

Код:

interface Identifiable<T> {
   T id();
}

interface Dao<E extends Identifiable<I>, I> {
   E loadById(I id);
}

class ChangedMonitor<E extends Identifiable<I>, I> {
   final private E original;
   final private ChangedCallback callback;
   final private Dao<E, I> dao;

   public ChangedMonitor(E original, Dao<E, I> dao, ChangedCallback callback) {
      this.callback = callback;
      this.original = original;
      this.dao = dao;
   }

   void monitorIt() {
      while (true) {
         if (original.equals(dao.loadById(original.id()))) {
            callback.changed();
         }
      }
   }
}


и взглянем на UserDao и User:

Код:

public class UserDao implements Dao<User, Long> {
   @Override
   public User loadById(Long id) {
      return new User();
   }
}

public class User implements Identifiable<Long> {
   @Override
   public Long id() {
      return null;
   }
}


Ну и пример использования:
Код:

      User user = new User();
      UserDao userDao = new UserDao();
      Light light = new Light();
      ChangedCallback callback = new LightOnCallback(light);
      ChangedMonitor<User, Long> changedMonitor = new ChangedMonitor<User, Long>(user, userDao, callback);
      changedMonitor.monitorIt();



Все ок. Не спеши Мишка размахивать руками увидев что UserDao реализует Dao, потому что это генерик - и я реализую именно Dao для User и Long! А не некий общий интерфейс.
Т.е. генерик - это способ выразить обобщенный алгоритм, но чтобы его использовать ты должен этот алгоритм "инстанциировать". Так вот UserDao это "инстанциирование" обобщенного алгоритма Dao для параметров User и Long.

А вот теперь главный СЮРПРИЗ!!! Кривость и недоделки генериков в Java.... И теперь Мишка можешь размахивать руками и кричать что ты прав Smile

Как я тут не распинался и не кричал - не реализуй в дао общий тип.. и вроде бы у меня все получилось... а вот и хер! В Java программист может написать и скомпилировать вот такой код:

Код:

    Dao dao = new UserDao();


Да - тут будут варнинги про использование сырого типа... НО ЭТО ВСЕГО ЛИШЬ ВАРНИНГИ а не ошибки! И получается что весь мой спор понапрасну.. и ты нарвешься на исключения.. и вобщем все жопа.

А вот в C# если ты реализуешь типа IDao<User, long> то ты уже НИКОГДА не присвоишь такой объект переменной с типом IDao. Ты даже не сможешь объявить переменную IDao - если в определении типа есть генерик, то будь добр укажи параметры!

Вот аналогичный код на C#:
Код:

    interface IIdentifiable<T>
    {
        T Id
        {
            get;
        }
    }

    interface IDao<E, I> where E : IIdentifiable<I>
    {
        E LoadById(I id);
    }

    class ChangedMonitor<E, I> where E : IIdentifiable<I>
    {
        readonly E original;
        readonly IDao<E, I> dao;
        readonly IChangedCallback callback;

        public ChangedMonitor(E original, IDao<E, I> dao, IChangedCallback callback)
        {
            this.original = original;
            this.dao = dao;
            this.callback = callback;
        }

        public void MonitorIt()
        {
            while (true)
            {
                if (original.Equals(dao.LoadById(original.Id)))
                {
                    callback.changed();
                }
            }
        }
    }

    interface IChangedCallback
    {
        void changed();
    }

    class User : IIdentifiable<long>
    {
        public long Id
        {
            get { throw new NotImplementedException(); }
        }
    }

    class UserDao : IDao<User, long>
    {
        public User LoadById(long id)
        {
            return new User();
        }
    }

    class Light
    {
        internal void On()
        {
        }
    }

    class LightOnCallback : IChangedCallback
    {
        Light light;

        public LightOnCallback(Light light)
        {
            this.light = light;
        }

        public void changed()
        {
            light.On();
        }
    }



Пример использования:
Код:

            Light light = new Light();
            LightOnCallback callback = new LightOnCallback(light);
            User user = new User();
            IDao<User, long> userDao = new UserDao();
            ChangedMonitor<User, long> monitor = new ChangedMonitor<User, long>(user, userDao, callback);
            monitor.MonitorIt();



И это еще не все. В Java такой код в итоге выразится в код со старыми "добрыми" кривыми dowb-cast'ами! И еще к тому же ударит по производительности. А вот в C# не будет в результирующем исполняемом коде полноценных кастов вообще - там будет легкий каст как статический каст в C++.

Вобщем вот так вот.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Snoopy



Зарегистрирован: 29.11.2005
Сообщения: 1395

СообщениеДобавлено: Сб Мар 07, 2009 2:52 am    Заголовок сообщения: Ответить с цитатой

teg писал(а):
И фсё? И драки не будет штоль?


Драка была в асе, это так - отголоски. Laughing

teg писал(а):
1. Нельзя расширять набор этих методов. Это обычно не соблюдается, потому что не удобно.


Вот тут подробнее... Если что-то нельзя, но делается - значит все-таки можно? А раз можно и удобно - почему бы и не?.. Wink

teg писал(а):
2. Это фсё будет имет смысл, если на самом деле не будет иерарахии. Т.е. если существует набор классов Кn, где n = 1,2,3...99 и для всех этих классов работает один DAO. И существует класс К100, для которого мы пишем DAO100, причём про это нихто не в курсе, потому чта мы работаем через базовый класс/интерфейс и экземпляр получаем через сервис-локатор.


Нет, постой! От сервиса-локатора мы будем получать уже экземпляр конкретного класса, а дальше мы уже можем использовать его как хотим - где-то как базовый интерфейс, а где-то и с поперечно-полосатыми getByName/getByUuid. В чем проблема-то?

teg писал(а):
Мишк, можешь кратко объяснить, зачем тебе наследование?


Чтоб иметь некую единую сущность, позволяющую единообразно работать с какими-то общими операциями над данной сущностью и при этом не быть ограниченным в добавлении к ней других операций.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Snoopy



Зарегистрирован: 29.11.2005
Сообщения: 1395

СообщениеДобавлено: Сб Мар 07, 2009 3:17 am    Заголовок сообщения: Ответить с цитатой

alsor писал(а):
итак, потягивая пулайнер...


Дразнишься, да?!! А я... А я зато ром сегодня пил! И опять не понравилось... Пахнет - офигенно приятно, а на вкус - бээээ. Моя рябиновка и то круче! Cool

alsor писал(а):
Не спеши Мишка размахивать руками увидев что UserDao реализует Dao, потому что это генерик - и я реализую именно Dao для User и Long! А не некий общий интерфейс.


Да за ради бога! Но вот ты можешь объяснить - почему твой UserDao не может быть, например, таким?

Код:

public class UserDao implements Dao<User, Long> {
   @Override
   public User loadById(Long id) {
      return new User();
   }

   public List<User> findByRole(Role role) {
      return ........
   }

   public List<User> findBanned() {
      return ........
   }
}


Кому это помешает и в каком месте? Идеологическое "так не положено" - не в счет, интересны конкретные примеры.

alsor писал(а):
А вот теперь главный СЮРПРИЗ!!! Кривость и недоделки генериков в Java...


Это опять офтоп. Я C# не знаю, поэтому готов тебе поверить, что там по сравнению с джавой в нем все красиво и шоколадно. Но если в джава дженерики сделаны хуже - то они хуже не только здесь - они хуже всегда. Но это никак не повод плюнуть на них и плодить, как ты предлагал изначально, сущности вручную.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Сб Мар 07, 2009 9:06 pm    Заголовок сообщения: Ответить с цитатой

Snoopy писал(а):
Да за ради бога! Но вот ты можешь объяснить - почему твой UserDao не может быть, например, таким?


Мишк, мы наверно с тобой о разных вещах тут говорим. Конечно мой дао может выглядить именно так как ты написал. Я и пытаюсь сказать что в дао будут в каждом свой набор методов весьма спецефичных для конкретного доменного объекта. С чего ты взял что я против этого?

Snoopy писал(а):
Я C# не знаю


Ну чтобы понять в чем суть - не нужно полностью знать C#. Разница лишь в том что если в C# тип парметризованный, т.е. Gereric - то программисту не позволено инстанциировать объекты без указания параметров. А в Java программист может просто на это забить. Но будем считать что такой программист сам себе злой буратино. А разумный человек возведет варнинги по использованию row type в разряд ошибок (хотя бы для себя в уме). Конечно в таком случае их можно и нужно использовать.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
dimitr



Зарегистрирован: 28.11.2005
Сообщения: 1124

СообщениеДобавлено: Сб Мар 07, 2009 9:29 pm    Заголовок сообщения: Ответить с цитатой

они схавали мой мозг... Shocked
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Сб Мар 07, 2009 9:31 pm    Заголовок сообщения: Ответить с цитатой

dimitr писал(а):
они схавали мой мозг...


Сори, Диман Smile Тебе не нужно было это читать )) Просто на форуме удобнее кусками кода друг в друга кидаться - по аське не так удобно.. вот мы и продолжили тут.
_________________
JIT happens!
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
teg



Зарегистрирован: 20.12.2005
Сообщения: 410

СообщениеДобавлено: Вс Мар 08, 2009 3:37 pm    Заголовок сообщения: Ответить с цитатой

Snoopy писал(а):

Вот тут подробнее... Если что-то нельзя, но делается - значит все-таки можно? А раз можно и удобно - почему бы и не?.. Wink

Нет, постой! От сервиса-локатора мы будем получать уже экземпляр конкретного класса, а дальше мы уже можем использовать его как хотим - где-то как базовый интерфейс, а где-то и с поперечно-полосатыми getByName/getByUuid. В чем проблема-то?

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

Можно -- умываться в унитазе.

А кто тебе такое сказал? А главное, не понял -- прочитай ещё раз и подумай. Я тут не про цвета совсем.

Чтоб иметь золотой микроскоп с лазерным наведением на гвозди, говоришь -- всё это отговариваю тебя от подобных желаний. А спросил я тебя, есть ли у тебя ПРИЧИНЫ на такие желания.


Приведу пример. Ща отвернулся от ГВТ кода, в котором завели базовый объект "Словарь" и навесили на него "Сериализуемо". Есть наследник -- "ПолеДеятельности". Базовый класс -- примитивщина: строка да ключ. А вот в наследнике -- коллекции-ассоциации. Всё это хозяйство ещё и в базу хайбером отображается. И всё это павидло уже не сериализуется. Так вот, нафига в базовом классе интерфейс?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
teg



Зарегистрирован: 20.12.2005
Сообщения: 410

СообщениеДобавлено: Вс Мар 08, 2009 3:45 pm    Заголовок сообщения: Ответить с цитатой

И потом, Михаил, своими примерами Вы демонстрируете типичное заблуждение по поводу DAO. Это не объекты доступа к данным. Это объекты уровня абстракции, позволяющего абстрагироваться от способов хранения и методов доступа к ним. Неоднократно указывалось, что изобретение реляционных баз данных, реализация стандарта SQL-92 и развитие дополнительных средств доступа к данным -- всё это начисто лишает разработчиков реализовывать алгоритмы в терминах DAO. Поэтому желание иметь какой-то хороший DAO -- очень странное желание. Хороший индеец...
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Snoopy



Зарегистрирован: 29.11.2005
Сообщения: 1395

СообщениеДобавлено: Вт Мар 10, 2009 11:27 am    Заголовок сообщения: Ответить с цитатой

2 alsor: Может и о разных. Я на всякий случай напомню, с чего все начиналось:

Цитата:

- что касается наследования - если уж ты наследуешь что-то, то единственное обоснование тому - полная подстановка - т.е. использование производного типа ровно так же как базового - потому что наследование имеет смысл только на уровне типа
...
- Ну тебя послушать - так при наследовании интерфейс вообще расширяться не может получается.
- ИМЕННО!


2 teg: Причина простая - мне это удобно. Ага, не идеология, а просто тупо удобно один раз описать метод в базовом классе/интерфейсе и одинаково использовать его в потомках. Разумеется случаи, когда он нафиг не сперся ни базовому, ни производному классу в расчет не берем - только вариант, когда метод 100% имеет смысл и там и там.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Вт Мар 10, 2009 12:09 pm    Заголовок сообщения: Ответить с цитатой

Snoopy писал(а):
Я на всякий случай напомню, с чего все начиналось


Ну я все еще придерживаюсь того же мнения.

Используя наследование - ты либо определяешь совершенно новый тип, который действительно будет подтипом другого, например, те же доменные объекты реализующие интерфейс RealName, тут ты будешь использовать объекты и как RealName тип и как некий конкретный тип User скажем.

Но чаще бывает что для какого-то кода который ты пишешь есть просто некий тип (или интерфейс), а все остальное это лишь реализация этого типа, и в этом случае расширять этот интерфейс нет смысла, особенно когда с твоим типом работает код который ты не можешь менять - например код фреймворка.

Что касается ДАО - здесь тот же принцип, только лишь с той разницей что я утверждаю что у ДАО не будет никакого общего типа. Т.е. весь твой код будет использовать ДОА как конкретный тип. А соответственно ты волен добавлять в ДАО очень спецефичные и всякие произвольные методы - именно по тому что ДАО будет везде в коде использоваться как его конкретный тип (и НИКОГДА как некий Dao). И соответственно нет смысла вводить базовый тип.

И опять же - то что я ввел интерфейс Dao<E, I> - это лишь для реализации кода с дженериками, но к сожалению в Java это потенциально может быть использовано как базовый тип - ХОТЯ ЭТО НЕ ТАК. Откуда вообще Java взяла тип Dao??? Я вообще не определял такого типа. Я определил ШАБЛОН Dao<E, I> и один его конкретный экземпляр - Dao<User, Long> Кстати читай это и трактуй так - UserDao это просто другое ИМЯ типа Dao<User, Long>. Откуда в моем коде взялся тип Dao?

И так суммируя - если в твоем последнем примере ты предлагал запихать методы findByRole и findBanned в интерфейс Dao<E, I> то это конечно не правильно.

Если ты просто определишь их в твоем классе - то это правильно, но с той оговоркой что Dao - это не базовый тип вообще.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Вт Мар 10, 2009 12:11 pm    Заголовок сообщения: Ответить с цитатой

Snoopy писал(а):
удобно один раз описать метод в базовом классе/интерфейсе и одинаково использовать его в потомках


ты уже неоднократно говришь такую фразу - приведи плиз конкретный пример из твоего кода, только пожалуйста пусть это не будет метод findById, а какой-нибудь другой.
_________________
JIT happens!
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Snoopy



Зарегистрирован: 29.11.2005
Сообщения: 1395

СообщениеДобавлено: Вт Мар 10, 2009 1:04 pm    Заголовок сообщения: Ответить с цитатой

alsor писал(а):

Но чаще бывает что для какого-то кода который ты пишешь есть просто некий тип (или интерфейс), а все остальное это лишь реализация этого типа


Ну Леш, давай все-таки определимся - так "чаще бывает" или это единственная возможность, для которой предназначено наследование? Согласись, "интерфейс вообще не может расширяться" - это скорее второе, чем первое?

alsor писал(а):

Что касается ДАО - здесь тот же принцип, только лишь с той разницей что я утверждаю что у ДАО не будет никакого общего типа.


Да почему, блин? Если у доменных объектов есть общий RealName и есть какой-то case его использования - почему не быть общему методу для его получения? Кроме идеологии - почему?

alsor писал(а):

И так суммируя - если в твоем последнем примере ты предлагал запихать методы findByRole и findBanned в интерфейс Dao<E, I> то это конечно не правильно.


Я предлагал запихать туда findById - и я в упор не понимаю, почему это неправильно.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Snoopy



Зарегистрирован: 29.11.2005
Сообщения: 1395

СообщениеДобавлено: Вт Мар 10, 2009 1:31 pm    Заголовок сообщения: Ответить с цитатой

alsor писал(а):

ты уже неоднократно говришь такую фразу - приведи плиз конкретный пример из твоего кода, только пожалуйста пусть это не будет метод findById, а какой-нибудь другой.


Леш, это уже, кажется, третий пример, который ты отвергаешь. Тебе не кажется, что это многовато и неспроста? Wink

Хорошо, давай вообще уйдем от DAO, доменных объектов и прочего. Вот есть какая-то игра, стратегия. В ней есть сущности: мотоцикл, грузовик, БТР, танк, стелс-танк. Все это, однозначно, транспортные средства, т.е. они могут более-менее единообразно перемещаться по карте, реализуя Vehicle.move(...). Но кроме этого
- грузовик и БТР еще должны уметь брать на борт людей (а грузовик - еще и снаряды при необходимости);
- БТР, танк и стелс - стрелять
- танк и стелс - переходить по дну реки
- стелс - становиться невидимым.

Пожалуйста, реализуй мне это без расширения базового типа, используя только агрегацию, а? Только не говори, плз, что "в ооп все не так, как в жизни" - тут ты сам волен выбирать реализацию и можешь сделать "не как в жизни", дело твое.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Вт Мар 10, 2009 4:23 pm    Заголовок сообщения: Ответить с цитатой

Snoopy писал(а):
Ну Леш, давай все-таки определимся - так "чаще бывает" или это единственная возможность, для которой предназначено наследование? Согласись, "интерфейс вообще не может расширяться" - это скорее второе, чем первое?


Я лишь пытаюсь сказать что есть тонкая разница между реализацией типа и введением нового под-типа. Разница эта скорее семантическая нежели синтаксическая, потому что и в том и другом случае ты вроде бы определяешь новый класс (что вроде бы трактуется как новый тип) и используешь наследование.
Ну например, вспомним Struts. Чтобы написать свой Action мы должны уаследоваться от базового Action. Но есть ли смысл если мы помимо публичных методов о которых "знает" struts (т.е. присутствующих в базовом классе) добавим в наш конкретный action еще несколько своих? Есть ли смысл брать и использовать некий свой Action не как базовый тип, а как конкретный тип? Помоему это явный признак кривизны в коде, свидетельствующий скорее всего о плохом разделении ответственности между классами. Причем я такое видел неоднократно в реальном коде.

Если же у тебя действительно есть некая иерархия типов, не только синтактически (extedns, implements) но самое важное - семантически, то новый под-тип привнесет дополнительное поведение. Ну например, пусть у нас есть тип Число, и мы вводим тип Комплексное Число - тогда конечно новый тип привнесет дополнительные методы.

Snoopy писал(а):
Да почему, блин? Если у доменных объектов есть общий RealName и есть какой-то case его использования - почему не быть общему методу для его получения? Кроме идеологии - почему?

Я предлагал запихать туда findById - и я в упор не понимаю, почему это неправильно.

Леш, это уже, кажется, третий пример, который ты отвергаешь. Тебе не кажется, что это многовато и неспроста?


Нет, ты приведи пример ИСПОЛЬЗОВАНИЯ такого общего метода.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Вт Мар 10, 2009 7:57 pm    Заголовок сообщения: Ответить с цитатой

Snoopy писал(а):
Хорошо, давай вообще уйдем от DAO, доменных объектов и прочего. Вот есть какая-то игра, стратегия. В ней есть сущности: мотоцикл, грузовик, БТР, танк, стелс-танк. Все это, однозначно, транспортные средства, т.е. они могут более-менее единообразно перемещаться по карте, реализуя Vehicle.move(...). Но кроме этого
- грузовик и БТР еще должны уметь брать на борт людей (а грузовик - еще и снаряды при необходимости);
- БТР, танк и стелс - стрелять
- танк и стелс - переходить по дну реки
- стелс - становиться невидимым.


Этот пример конечно поинтереснее... я его дома поделаю. Но у меня уже есть несколько мыслей:
- во-первых, тут у тебя явно несколько типов - Двигающееся, Перевозящее_людей, Перевозящее_Груз, Стреляющее, Водоплавающее, Невидимое.
- во-вторых, с чего ты взял что эти типы необходимо выстраивать в иерархию? Для меня например совершенно не очевидно что здесь должно быть под-типом чего и супер-типом чего. Я здесь не вижу иерархию вообще. Однако нужна она или нет покажут только тесты (ну или остальной код игры).

Скорее всего какой-то объект будет реализовывать несколько из приведенных типов - например Танк : Стреляющее, Двигающееся, Водоплавющее. И то еще не факт! Это лишь при необходимости иметь возможность ссылаться на него как на единое целое (а это будет зависеть от остального кода игры, например подсистеме решающей преодолеет объект препятствие или нет совершенно не важно танк это или стелс). Но опять же - Танк скорее всего не будет определять каких-то других публичных методов кроме тех что присутствуют в перечисленных типах.

Цитата:
Только не говори, плз, что "в ооп все не так, как в жизни" - тут ты сам волен выбирать реализацию и можешь сделать "не как в жизни", дело твое


А вот как раз если ты попытаешься смоделировать объекты исходя из того что они из себя представляют в реальной жизни - вот тут ты и наплодишь ненужных иерархий. Не только не нужных, да еще и необоснованных. Ведь для тебя (и для меня) совершенно очевидно что Танк есть нечто стреляющее, и притом это движущееся средство - соответственно легко сделать вывод что Стреляющее это под-тип Движащегося - бред.

Вобщем как я всегда говорю - только тесты покажут.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
teg



Зарегистрирован: 20.12.2005
Сообщения: 410

СообщениеДобавлено: Вт Мар 10, 2009 11:07 pm    Заголовок сообщения: Ответить с цитатой

Snoopy писал(а):
Пожалуйста, реализуй мне это без расширения базового типа, используя только агрегацию, а? Только не говори, плз, что "в ооп все не так, как в жизни" - тут ты сам волен выбирать реализацию и можешь сделать "не как в жизни", дело твое.

Ну, собственно, именно так и надо делать. Именно потому, что это жизнь. При попытке соорудить общего предка получишь хрень какую-нибудь.

Полосатыми могут быть зебра, танк и банка пива. И ты на протяжении уже долгого времени пытаешься сказать, что это удобно -- захреначить им общего предка. Да, Майк это удобно. Но ровно до того момента, когда появится ещё какая-нибудь хрень. Вдруг окажется, что танки, деревья и плесень -- зелёные.

Т.е. пялясь на пару DAO ты никогда не сможешь понять, почему вкрячить им общего наследника -- ересь и бред. На множестве этих двух кренделей все твои утверждения -- истина. Но использование данной стратении в реальой разработке неминуемо заведёт тебя в тупик.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Snoopy



Зарегистрирован: 29.11.2005
Сообщения: 1395

СообщениеДобавлено: Ср Мар 11, 2009 12:20 am    Заголовок сообщения: Ответить с цитатой

teg писал(а):

При попытке соорудить общего предка получишь хрень какую-нибудь.


При попытке соорудить предка я получу нечто, что может ездить по карте - и смогу этим "нечто" нормально управлять. А вот что получите вы с алсором, если попытаетесь для каждого вида юнита писать свой собственный обслуживающий код - я очень даже хочу посмотреть. Особенно когда эти юниты понадобится собрать в кучку и вместе отправить громить вражескую базу.

teg писал(а):

Полосатыми могут быть зебра, танк и банка пива.


Так отменим же наследование, граждане! Fortran - наше фсё!
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
teg



Зарегистрирован: 20.12.2005
Сообщения: 410

СообщениеДобавлено: Ср Мар 11, 2009 12:29 am    Заголовок сообщения: Ответить с цитатой

может ездить по карте - и смогу этим "нечто" нормально управлять.

это не единственный способ достичь указанной цели, и это, естественно, не критерий. Ну в общем, Майк, Вы просто демонстрируете не владение основами ООП.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Snoopy



Зарегистрирован: 29.11.2005
Сообщения: 1395

СообщениеДобавлено: Ср Мар 11, 2009 1:38 am    Заголовок сообщения: Ответить с цитатой

teg писал(а):
это не единственный способ достичь указанной цели, и это, естественно, не критерий. Ну в общем, Майк, Вы просто демонстрируете не владение основами ООП.


Бла-бла-бла-бла-бла... Twisted Evil
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Ср Мар 11, 2009 3:03 am    Заголовок сообщения: Ответить с цитатой

Итак... игра!

Я только начал что-то делать с предложенной тобой игрой, но уже четко видно что это абсолютно не про иерархию юнитов...

Вкратце расскажу как мой код эволюционировал в процессе разработки через test-first:

    Сначала я решил реализовать самое простейшее - например заставить некий Юнит передвинуться на одну ячейку на восток. Но при этом, если на востоке у нас река, то Танк пройдет, а Грузовик нет. И тут дествительно я сделал тип Unit, от него наследуются Tank и Truck. При этом Tank еще и реализует интерфейс Floating. И типа ячейка River решает кто сможет пройти. Все ок.

    Но на этом собственно и все! Дальше мне никакая иерархия не поможет. Я теперь решил реализовать что-то посложнее - спобоность стрелять. И при этом сразу задумываешься об аспекте управления в игре - ведь игрок выделяет некий юнит (заметь мы работаем с объектом Unit) и отдает ему команды. Ну например ты сам в предыдущем посте сказал что хочешь выделить кучку юнитов и заставить атаковать что-то, т.е. ты будешь работать с ними как Unit'ами, а не как с Танком, двумя Грузовиками и ПолевойКухней. Заметь не все умеют стрелять - но команды ты отдашь всем. А вот теперь прикол - интерфейс объекта Unit должен содержать все возможные команды всех юнитов! И конечно же дальше идти в русле иерархии объектов-юнитов смысла нет... у меня будет куча куча методов половина из которых в классах потомках будут пустышками - ну согласись бред. Да и тем более если я хочу реализовать все аддитивно, то конечно же напрашивается что-то типа unit.doCommand("fire").

    Итак, собственно уже вырисовывается что наиболее важными объектами будут совершенно не юниты, а некие Команды, которые при наличии определенных Способностей будут каким-то образом выполняться в текушем состоянии объекта (положение на карте, наличие патронов и прочее). Собственно Команды у меня пока просто строки (пока хватает), а способности это тип Ability. И вот как раз на способностях нужно будет сосредоточиться. Некоторые из них будут направлены на себя (уйти в стелс, загрузиться/разгрузиться), некоторые будут направлены на других юнитов (стрельнуть в ячейку (2,4) и нанести урон если там юнит), некоторые на преодоление препятствий.

    А что же стало с юнитами? А Unit это всего лишь некий контейнер Способностей и объект хранящий свое текущее состояние в игре.


Вобщем пока у меня как-то вот так... посмотрим во что это выльется дальше - могу все и поменять Smile
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Snoopy



Зарегистрирован: 29.11.2005
Сообщения: 1395

СообщениеДобавлено: Ср Мар 11, 2009 11:19 am    Заголовок сообщения: Ответить с цитатой

alsor писал(а):
у меня будет куча куча методов половина из которых в классах потомках будут пустышками


Конечно, если ты, как и хотел изначально, запихаешь их все в класс-предок. Но речь как раз о том и идет, чтобы так не делать! Более того - выделив способности в отдельную сущность ты не избавился от этой ситуации, а только усугубил ее - теперь, по сути, набор методов у юнитов стал динамическим, и ты, при известной доле криворукости, можешь получить двухколесный танк и водоплавающий грузовик.

alsor писал(а):
посмотрим во что это выльется дальше


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

PS Кстати то, что ты пытаешься сделать с командами и способностями - считай Smalltalk в чистом виде. Там вообще можно кому угодно передать какое угодно сообщение, исполнение которого будет зависеть от наличия в классе соответствующего метода-обработчика (а если его нет - от того, что будет задано в doesNotUnderstand()). Казалось бы - полная динамика, твори чо хошь! Но почему-то там все равно никто не призывает на этом основании отказаться от наследования - странно, да?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Ср Мар 11, 2009 12:40 pm    Заголовок сообщения: Ответить с цитатой

Snoopy писал(а):
Конечно, если ты, как и хотел изначально, запихаешь их все в класс-предок. Но речь как раз о том и идет, чтобы так не делать! Более того - выделив способности в отдельную сущность ты не избавился от этой ситуации, а только усугубил ее - теперь, по сути, набор методов у юнитов стал динамическим, и ты, при известной доле криворукости, можешь получить двухколесный танк и водоплавающий грузовик.


Но я же тебе обосновал почему мне это понадобилось... разве нет? Приведи мне тогда пример своего кода где ты управляешь юнитами которые имеют такую иерархию в своих типах. Только пожалуйста не приводи мне структуру самих классов - приведи пример их использования. Ты мне кстати так и ни привел НИ одного такого примера - используй свой собственный код и ты увидишь в чем его проблемы.

Snoopy писал(а):
Дальше, если ты попытаешься заставить способности выполнять какие-то действия над объектом, это выльется в иерархию способностей. Если сделаешь их, как и команды, чисто информационными, а само действие вынесешь в какой-то другой класс - в иерархию этих классов. А скорее всего - и в то, и в другое сразу.


Не знаю не знаю... увидим. Может ты прав, может нет... тесты покажут. Smile

Snoopy писал(а):
Но почему-то там все равно никто не призывает на этом основании отказаться от наследования - странно, да?


Да я не призываю избавляться от наследования - я сам его использую. Я лишь утверждаю что наследование часто используется там где его не болжно быть и используется не по назначению, и это приводит чаще всего к тому что программист сам себя загоняет в какие-то искуственно созданные рамки из которых сложно выбраться.
Там где наследование обоснованно - а именно там где тебе необходимо унаследовать ПРЕЖДЕ ВСЕГО ТИП - там НИЧЕМ другим кроме наследования не обойдешься.

Но все же Мишк - пример пожалуйста! Пример ИСПОЛЬЗОВАНИЯ таких объектов, не их структуру. Фразой "бла-бла..." ты нас упрекаешь в голословности, а сам не привел ни одного примера. А я тебе тут целые проекты кидаю..
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
teg



Зарегистрирован: 20.12.2005
Сообщения: 410

СообщениеДобавлено: Ср Мар 11, 2009 1:43 pm    Заголовок сообщения: Ответить с цитатой

Лёх, учись. Второй раз показывать не буду:

Код:
Unit u = getNextUnit();
if (u instnceof Tank) {
    //blah
} else if (u instanceof Truck) {
    //blah
} else if (u instanceof ManWithGun) {
    //blah
} else {
    throw new IllegalStateException("Засунь свой бесполезный Unit -- с ним ничего сделать нельзя");
}
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
alsor



Зарегистрирован: 25.11.2005
Сообщения: 1166
Откуда: Киберпространство

СообщениеДобавлено: Ср Мар 11, 2009 1:45 pm    Заголовок сообщения: Ответить с цитатой

Я этого и боялся Smile
_________________
JIT happens!
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Показать сообщения:   
Начать новую тему   Ответить на тему    Список форумов forum.alsor.net -> IT-форум Часовой пояс: GMT + 4
На страницу Пред.  1, 2, 3, 4  След.
Страница 2 из 4

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


Powered by phpBB © 2001, 2005 phpBB Group
Русская поддержка phpBB