Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> JAVA или .NET ? обсуждаем достоинства и недостатки 
:(
    Опции темы
Allexx
Дата 3.2.2004, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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




M
mr.DUDA
Вопросы, мнения и просто свои мысли по поводу особенностей платформы .NET в сравнении с JAVA можно обсудить в этой теме. В любых других темах замечания типа "JAVA (или .NET) круче!" будут являться оффтопом, даже в том случае, если они аргументированы :).

P.S. аналогичная тема есть в разделе по JAVA.

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


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 9
Всего: 172





--------------------

PM   Вверх
stab
Дата 9.4.2005, 15:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



И так, обобщая по обработке событий в .NET и Java.

1. Java.

1.1 Событие.

На уровне языка понятие события отсутсвует, его вынесли на прикладной уровень или не внесли оттуда smile Каждый класс\объект, который заявляет о желании опубликовать событие, должен:

а. Самостоятельно поддерживать внутренний список всех подписавшихся на событие объектов.
b. Реализовать методы для добавления\удаления подписчиков из внутреннего списка подписавшихся.
c. Опубликовать соответствующий интерфейс, который должен быть реализован каждым из объектов-подписчиков.

Каких-то строгих требований к реализации, судя по всему, нет.

1.2 Обработчик события (подписчик).

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

1.3 Код.

Прошу знатоков Java привести полный код класса публикующего событие и пример работы с ним.



2. .NET (C#)

2.1 Событие.

Понятие события введено на уровне языка. Каждый класс\объект, который заявляет о желании опубликовать событие, должен:

а. Объявить соответствующий класс-делегат с требуемой сигнатурой.
b. Объявить соответствующий член-событие.

Этот член-событие, по сути, является объектом-списком (System.MulticastDelegate) объектов-делегатов (System.Delegate), который реализует всю функциональность по поддержанию списка, добавлению\удалению подписчиков и по оповещению о наступлении события.

2.2 Обработчик события (подписчик).

Обработчиком события может быть любой метод с подходящей сигнатурой. Для добавления в список подписчиков информация о методе инкапсулируется в объекте класса System.Delegate.

2.3 Код. (C# 2.0)

Класс с событием:
Код

using System;
...

public delegate void SampleEventHandler();

public class ClassWithEvent
{
    public event SampleEventHandler SampleEvent;

    public void DoSampleEvent()
    {
        if (SampleEvent != null) SampleEvent();
    }
}


Пример работы:
Код

using System;
...

class Program
{
    static public void Main()
    {
        ClassWithEvent testObject = new ClassWithEvent();
        testObject.SampleEvent += FirstHandler;
        testObject.SampleEvent += SecondHandler;
        testObject.DoSampleEvent();
    }

    static private void FirstHandler()
    {
        Console.WriteLine("FirstHandler");
    }

    static private void SecondHandler()
    {
        Console.WriteLine("SecondHandler");
    }
}


или так:
Код

using System;
...

class Program
{
    static public void Main()
    {
        ClassWithEvent testObject = new ClassWithEvent();
        testObject.SampleEvent += delegate
        {
            Console.WriteLine("FirstHandler");
        };

        testObject.SampleEvent += delegate
        {
            Console.WriteLine("SecondHandler");
        };

        testObject.DoSampleEvent();
    }
}



--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
Domestic Cat
Дата 9.4.2005, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 9
Всего: 172



Код

interface Listener
{
    void stateChanged();    
}

class SomeClass
{
    int state;
    ArrayList<Listener> listeners = new ArrayList<Listener>();

    public void setState(int state)
    {
        this.state = state;
        fireStateChanged();    
    }    
    
    protected fireStateChanged()
    {
        for(Listener l : listeners)
            l.stateChanged();    
    }
    
    public void addListener(Listener l)
    {
        listeners.add(l);
    }
}

class MyClass implements Listener
{
    MyClass()
    {
        SomeClass some = new SomeClass();
        some.addListener(this);
        some.addListener(this);    
    }
    
    public void stateChanged()
    {
        // do something;    
    }    



Несколько замечаний.
1. За все время мне пришлось самому реализовывать такую вещь один единственный раз. И J2SE, и J2EE содержат достаточное количество листенеров на все случаи жизни. В таких случаях все сводится к
Код

class MyClass implements StateListener
{
    MyClass()
    {
        SomeClass some = new SomeClass();
        some.addStateListener(this);
    }
    
    public void stateChanged()
    {
        // do something;    
    }    


что никак не сложнее делегатов.
Если говорить о самой системе листенеров (см. пример выше)
Недостаток - писать больше, реально - не намного.
Недостатки делегатов, имо:
1. Отсутствие соглашения об именовании делегатов и методов. Можно назвать как хочешь, причем даже осмысленное название часто трудно отличить от названия метода/класса/поля.
2. Делегаты скрывают в себе много автогенерированного кода, внутренний механизм их действия труднее понять.
3. Делегаты, помимо введения двух кейвордов, вводят лишнюю сущность в языке - ссылку на метод, которая более нигде не используется.
4. "Извне" трудно понять, что такое делегат - метод или класс. С одной стороны, это класс, объект которого можно создать через new, с другой стороны, вызывается он как метод.
5. Делегат не может иметь больше одного метода. Часто же нужно несколько методов, сгруппированных по к-л признаку. Например, Java интерфейс MouseListener содержит 5 методов, тогда как в C# требуется 5 делегатов (и, следовательно, 5 классов).
6. Java листенеры более гибки, если я реализую такой листенер сам, у меня есть выбор - как хранить листенеры, в каком порядке вызывать методы, реализовать другие, вспомогательные методы.


--------------------

PM   Вверх
batigoal
Дата 9.4.2005, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


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

Репутация: 1
Всего: 151



Цитата(Domestic @ 9.4.2005, 20:17)
Например, Java интерфейс MouseListener содержит 5 методов, тогда как в C# требуется 5 делегатов (и, следовательно, 5 классов).

Вдогонку - если нам нужно, скажем, только два метода из этих пяти, можно воспользоваться классом-адаптером и переопределить только нужные нам методы. Для остальных будет использована пустая реализация. Мелочь, а приятно.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
mr.DUDA
Дата 10.4.2005, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Цитата(Domestic @ 9.4.2005, 20:17)
Java листенеры более гибки, если я реализую такой листенер сам, у меня есть выбор - как хранить листенеры, в каком порядке вызывать методы, реализовать другие, вспомогательные методы

В общем, всё сводится к "напишу-ка я всё сам". Т.е. по сути дела, листенеры вообще не нужны, ведь можно обойтись и без них.

"Лишний" автогенерируемый код, на самом деле, весь лежит в базовом классе Delegate. Если взять и дизассемблировать сборку, содержащую делегат, в его коде будет всего 3 перекрытых типизированных метода базового класса и конструктор.

Возможности, предоставляемые делегатами:
1) Имея объект "делегат", можно получить ссылку на объект содержащий метод (свойство Target), reflection-описание метода (Method);
2) Можно перечислить список всех объектов и их методов, подписанных на делегат (GetInvokeList);
3) Можно вызвать метод(ы), подписанные на делегат, асинхронно!!! Примеры - в MSDN. Умеют ли это листенеры?
4) Можно вызывать метод-подписчик с использованием позднего связывания (late-bound) - метод DynamicInvoke;
5) Можно комбинировать делегаты (метод Combine).

Наконец, в листенерах приходится пользоваться switch-ем, а это уже напоминает подход WinAPI.


--------------------
user posted image
PM MAIL WWW   Вверх
Domestic Cat
Дата 10.4.2005, 08:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 9
Всего: 172



Цитата(mr @ 9.4.2005, 23:14)
1) Имея объект "делегат", можно получить ссылку на объект содержащий метод (свойство Target), reflection-описание метода (Method);


Но ведь то же можно делать и с листенером.
Цитата(mr @ 9.4.2005, 23:14)
2) Можно перечислить список всех объектов и их методов, подписанных на делегат (GetInvokeList);

Все классы в Java, поддерживающие слушателей, имеют методы get<...>Listeners()

Цитата(mr @ 9.4.2005, 23:14)
3) Можно вызвать метод(ы), подписанные на делегат, асинхронно!!! Примеры - в MSDN. Умеют ли это листенеры?

Это свойство не делегатов, а фича языка. В Java есть асинхронный вызов методов, см http://java.sun.com/j2se/1.5.0/docs/api/ja...FutureTask.html

Цитата
4) Можно вызывать метод-подписчик с использованием позднего связывания (late-bound) - метод DynamicInvoke;

Вот с этим я не разбирался, можно пример, чтобы знать о чем речь?

Цитата(mr @ 9.4.2005, 23:14)
5) Можно комбинировать делегаты (метод Combine).

Ну, это то же самое что и +=, и то же самое что просто добавление еще одного листенера в Java.

Цитата(mr @ 9.4.2005, 23:14)

Наконец, в листенерах приходится пользоваться switch-ем, а это уже напоминает подход WinAPI.

Сильно сказано; во-первых это не такое уж супер частое явление, во-вторых та же Простая Фабрика пользует свич, но это не значит, что паттерн является чисто процедурным и пришел из винапи smile


--------------------

PM   Вверх
mr.DUDA
Дата 10.4.2005, 08:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Цитата(Domestic @ 10.4.2005, 08:25)
5) Можно комбинировать делегаты (метод Combine).

Ну, это то же самое что и +=, и то же самое что просто добавление еще одного листенера в Java.

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


Цитата(Domestic @ 10.4.2005, 08:25)
Вот с этим я не разбирался, можно пример, чтобы знать о чем речь?

Вот пример:
Код

    public delegate string MyDelegate(string a, int c);

    public class Test
    {
        // этот метод будем вызывать асинхронно
        string Function(string a, int b)
        {
            /* какие-то действия */
            System.Threading.Thread.Sleep(5000);

            return "Результат метода";
        }

        // Можно так
        public void DoSomeAsyncronously()
        {
            MyDelegate deleg = new MyDelegate(this.Function);

            // вызываем метод "Function" асинхронно
            IAsyncResult ar = deleg.BeginInvoke(
                "111", 123, // это - аргументы метода
                null, null // а это - доп. параметры
                );

            // ждём не более 10 секунд
            ar.AsyncWaitHandle.WaitOne(10000, false);

            // если завершился за 10 секунд - получим результат
            if(ar.IsCompleted)
            {
                string result = deleg.EndInvoke(ar);
            }
        }

        // А можно и вот так
        public void StartAsyncMethod()
        {
            MyDelegate deleg = new MyDelegate(this.Function);
            deleg.BeginInvoke("123", 456, new AsyncCallback(this.OnAsyncMethodFinished), deleg);
        }
        public void OnAsyncMethodFinished(IAsyncResult ar)
        {
            MyDelegate deleg = (MyDelegate) ar.AsyncState;
            string result = deleg.EndInvoke(ar);
        }
    }

Добавлено @ 08:51
З.Ы. неужели, кроме делегатов, никаких принципиальных отличий .NET от JAVA нету ?


--------------------
user posted image
PM MAIL WWW   Вверх
Domestic Cat
Дата 10.4.2005, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 9
Всего: 172



Цитата(mr @ 9.4.2005, 23:49)
З.Ы. неужели, кроме делегатов, никаких принципиальных отличий .NET от JAVA нету ?


Есть конечно, но пока из делегатов выбраться не можем smile


Цитата(mr @ 9.4.2005, 23:49)
Вот пример:

Я пропустил там цитату
Цитата
4) Можно вызывать метод-подписчик с использованием позднего связывания (late-bound) - метод DynamicInvoke;

то есть вопрос был о DynamicInvoke, не об асинхронном вызове..
Но все равно спасибо.


--------------------

PM   Вверх
mr.DUDA
Дата 10.4.2005, 09:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Цитата(Domestic @ 10.4.2005, 09:24)
вопрос был о DynamicInvoke, не об асинхронном вызове..

Здесь всё просто. Так как все делегаты наследуются от базового класса Delegate, можно хранить и передавать объекты Delegate вместо "конкретных" (типизированных) делегатов. Чтобы вызывать методы, подписанные на такой делегат, и используется DynamicInvoke. Другими словами, можно вызвать любой делегат с любым кол-вом и типом аргументов, используя одну и ту же функцию DynamicInvoke.

Термин "late binding" здесь означает позднее связывание (конкретные типы объектов неизвестны на этапе компиляции кода).


--------------------
user posted image
PM MAIL WWW   Вверх
Domestic Cat
Дата 10.4.2005, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 9
Всего: 172



Проще говоря, использовать рефлекшн для вызова метода? В Java рефлекшн есть, потому не проблема.


--------------------

PM   Вверх
mr.DUDA
Дата 10.4.2005, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Кстати, а в JAVA можно передать в метод переменное количество аргументов ? Без рефлекшн, конечно.


--------------------
user posted image
PM MAIL WWW   Вверх
Domestic Cat
Дата 10.4.2005, 10:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 9
Всего: 172



Можно:
Код


class Hello
{
      public static void main(String... args)
      {
            for(String s : args)
                System.out.println(s);
      }
}




--------------------

PM   Вверх
alir
Дата 10.4.2005, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата
Приколист, .НЕТ ведь только под виндуза заточет, а в простой мобиле(не смартфоны!) даже операционной системы нет.

Я смотрю это ты приколист! .NET вначале проектировался как работающий на любой os, а не только под win. Пока еще есть под freeBSD - и это только начало. И что на счет os? .NET также построен на независимых средствах VM - так что встроить .net в мобилы в будущем тоже реально!

Цитата
оперативки чтоли?  Если постояной, то только через флешки наращивают.

Но ведь раньше и этого не было - примерно год назад (я имею ввиду Россию) вообще за 5 мб не переходило. А сейчас в 16 раз больше + еще карты!

Цитата
Упаси Бог! Хотя этого и так не будет...

Ты не бойся - как-нить разберутся.

p.s. Хотя еще раз повторюсь:
скорее всего скоро мобилы уйдут - они полностью перейдут смартофоны. Вот там то .net возьмет свое.
PM MAIL ICQ   Вверх
stab
Дата 12.4.2005, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



Цитата
1. Отсутствие соглашения об именовании делегатов и методов. Можно назвать как хочешь, причем даже осмысленное название часто трудно отличить от названия метода/класса/поля.


Соглашение есть:

Класс-делегат: XxxEventHandler
Событие: Xxx
Обработчик: ИмяОбъекта_Xxx

Удобно то, что вся работа с событием сгруппирована минимум в одном члене, в Java же требуется минимум 1 приватный член плюс 2 публичных.

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


Это называется инкапсуляция. Сомневаюсь, что Java-разработчики имеют исходный код всех классов с которыми работают, вроде на понимании это не сильно сказалось, правда? ;)

Цитата
3. Делегаты, помимо введения двух кейвордов, вводят лишнюю сущность в языке - ссылку на метод, которая более нигде не используется.


А где она (сущность) еще должна использоваться? Понятие "ссылки на метод" присутствует практически во всех современных языках, кроме Java, уж в C++ и Delphi точно есть.

Цитата
4. "Извне" трудно понять, что такое делегат - метод или класс. С одной стороны, это класс, объект которого можно создать через new, с другой стороны, вызывается он как метод.


Можно работать полностью как с объектом, если это требуется. Напоминает спор о свойствах, многие сишники говорят, что это тоже лишний элемент. Им не нравится то, что обращение к свойству не возможно отличить от обращения к полю. Им по душе использовать пару методов getXxx, setXxx, а в это время все языки обзавелись свойствами smile

Цитата
5. Делегат не может иметь больше одного метода. Часто же нужно несколько методов, сгруппированных по к-л признаку. Например, Java интерфейс MouseListener содержит 5 методов, тогда как в C# требуется 5 делегатов (и, следовательно, 5 классов).


Но в тоже время, на каждый обработчик в Java требуется отдельный класс. И еще, представим такую картину: нам нужно обработать только событие MouseDown, в C# назначем обработчик и все. В Java нужно реализовать все пять методов, т.к. требуется реализовать интерфейс, получаем четыри совершенно ненужных и пустых метода.

Цитата
6. Java листенеры более гибки, если я реализую такой листенер сам, у меня есть выбор - как хранить листенеры, в каком порядке вызывать методы, реализовать другие, вспомогательные методы.


Имеется возможность ручками обрабатывать добавление\удаление обработчиков:

Код

public event MyDelegate MyEvent
{
    add 
    {
        // добавляем как хотим и куда хотим
    }

    remove
    {
        // удалем как хотим и откуда хотим
    }
}


и ручками вызывать обработчики в каком угодно порядке:

Код

public delegate void SampleEventHandler();

public class ClassWithEvent
{
    public event SampleEventHandler SampleEvent;

    public void DoSampleEvent()
    {
        if (SampleEvent != null)
        {
            Delegate[] invocationList = SampleEvent.GetInvocationList();
            foreach (SampleEventHandler handler in invocationList)
            {
                handler();
            }
        }
    }
}



--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
batigoal
Дата 12.4.2005, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


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

Репутация: 1
Всего: 151



Цитата(cully @ 12.4.2005, 12:31)
Но в тоже время, на каждый обработчик в Java требуется отдельный класс

Отнюдь. Зачем же? Один объект может слушать неограниченное количество событий одинакового или разного типа.
Код

class Listener implements xxxListener, yyyListener{...}
...
Listener obj = new Listener();
a.addXXXListener(obj);
b.addYYYListener(obj);

Цитата(cully @ 12.4.2005, 12:31)
В Java нужно реализовать все пять методов

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

Давайте уже выйдем, наконец, за пределы обработки событий. Я не знаком с .NET, мне интересно, какие еще есть различия. smile


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

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


 




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


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

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