Unintrusive Retroactive Polymorphism
От: c-smile Канада http://terrainformatica.com
Дата: 05.01.05 05:14
Оценка: 91 (11)
Наткнулся вот на Heron Programming Language

В котором замечена интересная концепция интерфейсов (вернее их как бы отсутствия)

retrofit polymorphism : Heron does not require a class to explicitly state which interfaces it implements, interface implementation is determined by whether the function signatures match


Т.е. интерфейс есть просто объявление списка функций который вы хотите получить от объекта:
Я выделил этот момент в тексте:

types {
    class Dog {
      MakeSound() : String {
        return "woof";
      }
      GetNumLegs() : Int {
        return 4;
      }
      GoFetch() {
        // ...
      }
    }

    class Duck {
      GetNumLegs() : Int {
        return 2;
      }
      MakeSound() : String {
        return "quack";
      }
      FlySouth() {
        // ...
      }
    }

    interface IAnimal {
      MakeSound() : String;
      GetNumOfLegs() : Int;
    }  }
  functions {
    _main() {
      IAnimal& animal;
      Dog dog;
      Duck duck;
      animal = @dog;
      P(animal.MakeSound()); // outputs woof
      animal = @duck;
      P(animal.MakeSound()); // outputs quack
    }
  }


Показалось интересным.
http://www.heron-language.com/interfaces.html
Там еще мысли по поводу meta programming наличествуют.
В общем кому интересно — гляньте.
Re: Unintrusive Retroactive Polymorphism
От: Павел Кузнецов  
Дата: 05.01.05 05:20
Оценка:
c-smile,

> Наткнулся вот на Heron Programming Language

> В котором замечена интересная концепция интерфейсов (вернее их как бы отсутствия)
>

> retrofit polymorphism : Heron does not require a class to explicitly state which interfaces it implements, interface implementation is determined by whether the function signatures match


Гм... Структурная совместимость типов. Скажем, в C++ выражена шаблонами. В чем новизна подхода Heron?.. Правильно ли я понял, что в том, что подход "легализован" на уровне "основного" синтаксиса языка?

> Показалось интересным.


+1. Спасибо.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: Unintrusive Retroactive Polymorphism
От: c-smile Канада http://terrainformatica.com
Дата: 05.01.05 05:28
Оценка: 4 (1) :)
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Гм... Структурная совместимость типов. Скажем, в C++ выражена шаблонами. В чем новизна подхода Heron?.. Правильно ли я понял, что в том, что подход "легализован" на уровне "основного" синтаксиса языка?


Да, легализован.

У автора кстати есть попытка имплементировать это в стиле boost на С++
http://www.codeproject.com/cpp/retrofitpolymorphism2.asp

>> Показалось интересным.


ПК>+1. Спасибо.


"Ниччо не нада"
Re: Unintrusive Retroactive Polymorphism
От: Зверёк Харьковский  
Дата: 05.01.05 07:12
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Наткнулся вот на Heron Programming Language

wow! очень занятно!
сам слушаю и вам рекомендую: Настя — Ветер
FAQ — це мiй ай-кью!
Re: Unintrusive Retroactive Polymorphism
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.01.05 09:37
Оценка: 7 (1) +3
Здравствуйте, c-smile, Вы писали:

CS>В котором замечена интересная концепция интерфейсов (вернее их как бы отсутствия)


А в чем замечательность? В том что не надо в классе указывать интерфейс? А какие от этого бенефиты, кроме повышения зависимости от опечаток?
... << RSDN@Home 1.1.4 beta 3 rev. 272>>
AVK Blog
Re[2]: Unintrusive Retroactive Polymorphism
От: c-smile Канада http://terrainformatica.com
Дата: 05.01.05 20:47
Оценка: +1
Здравствуйте, AndrewVK, Вы писали:

AVK>А в чем замечательность? В том что не надо в классе указывать интерфейс? А какие от этого бенефиты, кроме повышения зависимости от опечаток?


Это совсем о другом на самом деле. Я так понимаю слово interface проинтерпретировано тобой в смысле C#
Здесь interface это больше механизм родственный template в C++.

Смотри, если ты в C++ говоришь

template<typename T>
  void foo(T& t) { t.bar(); }


То тем самым ты неявно ожидаешь что T будет иметь метод [something] bar();
Т.е. ожидаешь от T имплементацию некоего интерфейса.

Вот эти вот "неявно" и "[something]" на самом деле не украшают картину templates в C++.

И еще одна мысль про такой способ описания interfaces — они жутко эффективные.

В .NET и Java получение ссылки на интерфейс от объекта:
ISomething ismt = (ISomething)obj;

вельми дорогостоящая операция.

В С++ вызов виртуальной функции тоже не сильно дешев.

В Heron же операция получения интерфейса

animal = @dog;


это фактически образование (compile time) таблицы method references — (this,funcptr)
Соответсвенно вызов такого "виртуального" метода — это вызов обычной невиртуальной функции.

Я считаю что механизм полезен и окажет свое воздействие на С++.
Re[3]: Unintrusive Retroactive Polymorphism
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.01.05 21:38
Оценка: 48 (1) +1
Здравствуйте, c-smile, Вы писали:

CS>Это совсем о другом на самом деле. Я так понимаю слово interface проинтерпретировано тобой в смысле C#

CS>Здесь interface это больше механизм родственный template в C++.

Он не родственный совсем, просто правила разрешения имен сходные. А по сути это интерфейс и есть. Только в отличие от шарпа не надо его явно указывать в самом классе.

CS>И еще одна мысль про такой способ описания interfaces — они жутко эффективные.


Да? А по мне так наоборот — для полиморфного кода при компиляции интерфейс неотрезолвить. Придется резолвить в рантайме.

CS>В .NET и Java получение ссылки на интерфейс от объекта:

CS>
CS>ISomething ismt = (ISomething)obj;
CS>

CS>вельми дорогостоящая операция.

Для джавы не знаю, а для дотнета нет, не дорогостоящая. В дотнете вобще один из самых быстрых (хотя и несколько более прожорливый в плане памяти) вариант реализации интерфейсов. В форуме по дотнету я как то подробно рассматривал как интерфейсы работают уже после работы JIT. В частности в таком коде:
class X : IX
{}

...

X x = new X();
IX ix = (IX)x;

На операцию приведения вобще никакого x86-кода не будет, JIT его просто выкинет. Т.е. в таком случае операция абсолютно эффективна. Ну а когда на этапе приведения при работе JIT заранее о результате неизвестно, там будет единственное обращение к interface map по константному смещению (любой интерфейс в imap всех классов всегда расположен по одному и тому же смещению). А вот в твоем варианте все намного печальнее — нужно будет сканировать символьные имена реального класса и интерфейса на предмет поиска соотвествий. Это можно конечно закешировать, но все равно до скорости дотнета не дотянуть.

CS>В С++ вызов виртуальной функции тоже не сильно дешев.


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

CS>В Heron же операция получения интерфейса


CS>
CS>animal = @dog;
CS>


CS>это фактически образование (compile time) таблицы method references — (this,funcptr)

CS>Соответсвенно вызов такого "виртуального" метода — это вызов обычной невиртуальной функции.

Т.е. в случае полиморфного кода это не работает? Тогда полезность этой фичи вобще непонятна.
... << RSDN@Home 1.1.4 beta 3 rev. 272>>
AVK Blog
Re[3]: Unintrusive Retroactive Polymorphism
От: Павел Кузнецов  
Дата: 05.01.05 21:40
Оценка:
c-smile,

> В .NET и Java получение ссылки на интерфейс от объекта:

>
> ISomething ismt = (ISomething)obj;
>

> вельми дорогостоящая операция.

А если в C# obj — value-тип, то использование полученной ссылки на интерфейс еще и чревато нарушением ожиданий программиста, т.к. ismt ссылается на (неявно созданную) копию, а не оригинальный obj.

> В Heron же операция получения интерфейса

>
> animal = @dog;
>

> это фактически образование (compile time) таблицы method references — (this,funcptr)

И что интересно, здесь, в отличие от примера выше с value-типами в C#, все будет работать, как ожидается. Т.е. изменения, осуществленные через ссылку на интерфейс animal, отразятся на объекте dog.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: Unintrusive Retroactive Polymorphism
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.01.05 22:02
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>А если в C# obj — value-тип, то использование полученной ссылки на интерфейс еще и чревато нарушением ожиданий программиста,


Вобще то любой нормальный программист о боксинге знает.
... << RSDN@Home 1.1.4 beta 3 rev. 272>>
AVK Blog
Re[4]: Unintrusive Retroactive Polymorphism
От: c-smile Канада http://terrainformatica.com
Дата: 05.01.05 22:49
Оценка: +1 -1
Здравствуйте, AndrewVK, Вы писали:

CS>>И еще одна мысль про такой способ описания interfaces — они жутко эффективные.

AVK>Да? А по мне так наоборот — для полиморфного кода при компиляции интерфейс неотрезолвить. Придется резолвить в рантайме.

В С++ template как раз и занимаются тем что "резолвят". Это если я правильно понял термин "полиморфный код".
Дело в том что в C# статического полиморфизма (templates) нет как класса. Он там наверное и не нужен. Т.е. в общеме-то С# к обсуждаемой проблеме как бы не причем. С#/NET это система "everything is an object" что в С/C++ далеко не всегда имеет место быть.

CS>>В .NET и Java получение ссылки на интерфейс от объекта:

CS>>
CS>>ISomething ismt = (ISomething)obj;
CS>>

CS>>вельми дорогостоящая операция.

AVK>Для джавы не знаю, а для дотнета нет, не дорогостоящая. В дотнете вобще один из самых быстрых (хотя и несколько более прожорливый в плане памяти) вариант реализации интерфейсов. В форуме по дотнету я как то подробно рассматривал как интерфейсы работают уже после работы JIT. В частности в таком коде:

...
Т.е. все таки дорогостоящая. Не по времени так по размеру.

AVK>На операцию приведения вобще никакого x86-кода не будет, JIT его просто выкинет. Т.е. в таком случае операция абсолютно эффективна. Ну а когда на этапе приведения при работе JIT заранее о результате неизвестно, там будет единственное обращение к interface map по константному смещению (любой интерфейс в imap всех классов всегда расположен по одному и тому же смещению). А вот в твоем варианте все намного печальнее — нужно будет сканировать символьные имена реального класса и интерфейса на предмет поиска соотвествий. Это можно конечно закешировать, но все равно до скорости дотнета не дотянуть.


Можешь прояснить такой момент: скажем у меня есть в сборке N интерфейсов и M классов.
Как я понимаю по твоей схеме каждый класс должен включать N entries под все возможные интерфейсы.
Т.е. имеем фактически N*M таблицу. Я правильно все понял?
А как осущесвляется inter assembly interface linkage тогда?

CS>>В С++ вызов виртуальной функции тоже не сильно дешев.


AVK>И виртуальность вызовов интерфейсов в некоторых случаях дотнетовский JIT способен устранить. Один из примеров — если в дженерике в констрейнте указан интерфейс, а потом в качестве параметра в него подставить структуру, реализующую этот интерфейс, то вызовы этого интерфейса не приведут к боксингу и будут невиртуальными.


Ну при использовании templates динамическая виртуальность заменяется на статическую. Что заведомо более эффективно.
Тот же самый ATL/WTL построен как раз на принципах минимизации исп. vtbl.

CS>>В Heron же операция получения интерфейса


CS>>
CS>>animal = @dog;
CS>>


CS>>это фактически образование (compile time) таблицы method references — (this,funcptr)

CS>>Соответсвенно вызов такого "виртуального" метода — это вызов обычной невиртуальной функции.

AVK>Т.е. в случае полиморфного кода это не работает? Тогда полезность этой фичи вобще непонятна.


Я совсем не понимаю что ты имеешь ввиду под "полиморфный код".

Когда я "забираю" интерфейс у какого-нибудь класса я при компиляции знаю его состав функций (сигнатуры)
и могу эффективно построить интерфейсную таблицу.
IAnimal animal;


в рантайм пустой (null) но присвоение устанавливает ему this плюс адрес на некую статическую таблицу построенную в
compile time.

пысы: Я не говорю и не говорил никогда что система используемая в .NET плохая. Она по своему и для своих задач хороша. Для ситуации когда everything is an object она может быть даже близка к идеалу.

Данный же конкретный Heron ближе и в струе эволюции C++. Т.е. в принципе концепт таких вот interface я считаю
прекрасно бы дополнил, развил механизм templates.
Плюс идеи (не нотация) meta-programming Heron я думаю тоже достойны рассмотрения.

"Я так думаю" (С) Мимино.
Re[5]: Unintrusive Retroactive Polymorphism
От: Павел Кузнецов  
Дата: 05.01.05 23:00
Оценка: :)
AndrewVK,

> ПК> А если в C# obj — value-тип, то использование полученной ссылки на интерфейс еще и чревато нарушением ожиданий программиста,


> Вобще то любой нормальный программист о боксинге знает.


Это не означает, что он его везде ожидает
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: Unintrusive Retroactive Polymorphism
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.01.05 23:25
Оценка: 16 (1)
Здравствуйте, c-smile, Вы писали:

CS>Дело в том что в C# статического полиморфизма (templates) нет как класса.


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

AVK>>Для джавы не знаю, а для дотнета нет, не дорогостоящая. В дотнете вобще один из самых быстрых (хотя и несколько более прожорливый в плане памяти) вариант реализации интерфейсов. В форуме по дотнету я как то подробно рассматривал как интерфейсы работают уже после работы JIT. В частности в таком коде:

CS>...
CS>Т.е. все таки дорогостоящая. Не по времени так по размеру.
Типа отмазался
Все относительно. Размер imap равен количеству загруженных на момент загрузки класса интерфейсов. Поскольку интерфейсов и классов как правило довольно конечное количество, то реальный перерасход памяти ничтожный. Опять же — все равно твое предположение совершенно неверно, поскольку дорогостояща в шарпе механика интерфейсов, но никак не механика приведения, о которой ты вел речь.

CS>Можешь прояснить такой момент: скажем у меня есть в сборке N интерфейсов и M классов.

CS>Как я понимаю по твоей схеме каждый класс должен включать N entries под все возможные интерфейсы.
CS>Т.е. имеем фактически N*M таблицу. Я правильно все понял?

Нет. Во-первых сборки тут совершенно не при чем. Во-вторых N = количеству загруженных на момент загрузки класса интерфейсов.

CS>А как осущесвляется inter assembly interface linkage тогда?


Так же. Никакой привязки к сборкам у этого механизма нет.

CS>Ну при использовании templates динамическая виртуальность заменяется на статическую. Что заведомо более эффективно.


Если на этапе компиляции известен и тип и шаблон.

CS>Тот же самый ATL/WTL построен как раз на принципах минимизации исп. vtbl.


Я в курсе. ИМХО экономия на спичках.

AVK>>Т.е. в случае полиморфного кода это не работает? Тогда полезность этой фичи вобще непонятна.


CS>Я совсем не понимаю что ты имеешь ввиду под "полиморфный код".


class Base {}

class C : Base, IA {}

interface IA {}

...

Base b = new C();
IA ia = (IA)b; // здесь компилятор отрезолвить интерфейс не может


CS>Когда я "забираю" интерфейс у какого-нибудь класса я при компиляции знаю его состав функций (сигнатуры)

CS>и могу эффективно построить интерфейсную таблицу.
CS>
CS>IAnimal animal;
CS>


А где гарантия что ты у класса вобще когда либо попросишь этот интерфейс? Или компилятор выполняет перемножение всех классов и всех интерфейсов и строит для всех валидных комбинаций таблицы?

CS>в рантайм пустой (null) но присвоение устанавливает ему this плюс адрес на некую статическую таблицу построенную в

CS>compile time.

Т.е. при динамической загрузке это работать не будет.

CS>Данный же конкретный Heron ближе и в струе эволюции C++. Т.е. в принципе концепт таких вот interface я считаю

CS>прекрасно бы дополнил, развил механизм templates.

Честно говоря особой полезности я так и не ощутил. Очень сомнительная фича.
... << RSDN@Home 1.1.4 beta 3 rev. 272>>
AVK Blog
Re[6]: Unintrusive Retroactive Polymorphism
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.01.05 23:25
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

>> Вобще то любой нормальный программист о боксинге знает.


ПК>Это не означает, что он его везде ожидает


Ну это примерно как вызов виртуальной функции в конструкторе в плюсах. Там типа тоже программист ожидает что все будет работать .
... << RSDN@Home 1.1.4 beta 3 rev. 272>>
AVK Blog
Re[6]: Unintrusive Retroactive Polymorphism
От: Павел Кузнецов  
Дата: 06.01.05 00:20
Оценка:
AndrewVK,

> CS>Когда я "забираю" интерфейс у какого-нибудь класса я при компиляции знаю его состав функций (сигнатуры)

> CS>и могу эффективно построить интерфейсную таблицу.
> CS>
> CS>IAnimal animal;
> CS>


> А где гарантия что ты у класса вобще когда либо попросишь этот интерфейс? Или компилятор выполняет перемножение всех классов и всех интерфейсов и строит для всех валидных комбинаций таблицы?


Нет, вместо этого он строит "интерфейсную таблицу" только в момент, когда встретит приведение класса к интерфейсу.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[7]: Unintrusive Retroactive Polymorphism
От: Павел Кузнецов  
Дата: 06.01.05 00:22
Оценка: 7 (1) +2 -1
AndrewVK,

>>> Вобще то любой нормальный программист о боксинге знает.


> ПК> Это не означает, что он его везде ожидает


> Ну это примерно как вызов виртуальной функции в конструкторе в плюсах. Там типа тоже программист ожидает что все будет работать .


Не совсем: тамошнему поведению объяснение исключительно в пожелании так сделать, в стремлении к безопасности, т.е. предотвратить работу с несконструированным классом. Боксинг же — следствие оптимизации.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[6]: Unintrusive Retroactive Polymorphism
От: c-smile Канада http://terrainformatica.com
Дата: 06.01.05 00:53
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, c-smile, Вы писали:


CS>>Дело в том что в C# статического полиморфизма (templates) нет как класса.


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


"Перегрузка функций" что имеется ввиду?


AVK>Все относительно. Размер imap равен количеству загруженных на момент загрузки класса интерфейсов. Поскольку интерфейсов и классов как правило довольно конечное количество, то реальный перерасход памяти ничтожный. Опять же — все равно твое предположение совершенно неверно, поскольку дорогостояща в шарпе механика интерфейсов, но никак не механика приведения, о которой ты вел речь.


Спасибо, т.е. как я понимаю динамическое построение этих imap перенесено в load time?

CS>>Можешь прояснить такой момент: скажем у меня есть в сборке N интерфейсов и M классов.

CS>>Как я понимаю по твоей схеме каждый класс должен включать N entries под все возможные интерфейсы.
CS>>Т.е. имеем фактически N*M таблицу. Я правильно все понял?

AVK>Нет. Во-первых сборки тут совершенно не при чем. Во-вторых N = количеству загруженных на момент загрузки класса интерфейсов.


Ясно. Т.е. ClassLoader как сущность "зарезана" сразу. Я правильно понял?

CS>>Ну при использовании templates динамическая виртуальность заменяется на статическую. Что заведомо более эффективно.


AVK>Если на этапе компиляции известен и тип и шаблон.


Да конечно. Но это известно в 99% случаев. Т.е. на 99% эффективно.
Для случаев когда не известно или когда это вредит принципиально (модульная независиомость, межязыковые интерфейсы)
есть всякие разные полезные механизмы.

CS>>Тот же самый ATL/WTL построен как раз на принципах минимизации исп. vtbl.

AVK>Я в курсе. ИМХО экономия на спичках.

В тех облястях где мне приходится работать эти "спички" называются шведскими. Каждая по 6 дюймов.

AVK>>>Т.е. в случае полиморфного кода это не работает? Тогда полезность этой фичи вобще непонятна.

CS>>Я совсем не понимаю что ты имеешь ввиду под "полиморфный код".

AVK>
AVK>class Base {}
AVK>class C : Base, IA {}
AVK>interface IA {}
AVK>...
AVK>Base b = new C();
AVK>IA ia = (IA)b; // здесь компилятор отрезолвить интерфейс не может
AVK>


А для чего его резолвить если он не используется? А если он используется то должен быть объявлен.
Или я не понял опять чего?

CS>>Когда я "забираю" интерфейс у какого-нибудь класса я при компиляции знаю его состав функций (сигнатуры)

CS>>и могу эффективно построить интерфейсную таблицу.
CS>>
CS>>IAnimal animal;
CS>>


AVK>А где гарантия что ты у класса вобще когда либо попросишь этот интерфейс? Или компилятор выполняет перемножение всех классов и всех интерфейсов и строит для всех валидных комбинаций таблицы?


Зачем ему перемножать?

IAnimal — это просто список сигнатур функций в compile time. В runtime это указатель на статическую таблицу адресов.
Получение (суть построение) такого списка ( таблицы адресов методов) для данного класса — тривиальная задача компилятора/компоновщика.

CS>>в рантайм пустой (null) но присвоение устанавливает ему this плюс адрес на некую статическую таблицу построенную в

CS>>compile time.
AVK>Т.е. при динамической загрузке это работать не будет.

Ты имеешь ввиду late binding в стиле IDispatch?
Если да, то я могу точно также динамически построить эту таблицу например по списку экспорта DLL.

Давай я еще раз подчеркну основные фенечки:

Polymorphism without Space Overhead
Because polymorphism is provided externally to a class, it means that any class can be used polymorphically and also that there is no overhead of vtable pointers within a class. Most OOP languages, if not all, require a significant overhead to provide polymorphic behaviour.

The only caveat is that the interface references are typically twice the width of an an ordinary reference ( technically this is not neccessarily the case, as I will explain below ). On the other hand the overhead of multiple interface implementation in other languages is considerably more significant.

Polymorphism only when Needed
Another advantage of the Heron interfaces approach, is that you don't need to incur any of the cost of run-time polymorphism, until when and if you explicitly require it. That cost includes the inability to inline functions, the performance hit of dynamic dispatch and the space overhead of function dispatch tables.



AVK>Честно говоря особой полезности я так и не ощутил. Очень сомнительная фича.

Для .NET, согласен, бенифитов не будет при выбранноей архитектуре. Более того — я так понимаю принципиально невыполнимая.
Re[7]: Unintrusive Retroactive Polymorphism
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 06.01.05 12:06
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Нет, вместо этого он строит "интерфейсную таблицу" только в момент, когда встретит приведение класса к интерфейсу.


Т.е. либо в полиморфном коде это не работает, либо он делает это в рантайме.
... << RSDN@Home 1.1.4 beta 3 rev. 272>>
AVK Blog
Re[7]: Unintrusive Retroactive Polymorphism
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 06.01.05 12:06
Оценка:
Здравствуйте, c-smile, Вы писали:

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


CS>"Перегрузка функций" что имеется ввиду?


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

CS>Спасибо, т.е. как я понимаю динамическое построение этих imap перенесено в load time?


Да.

AVK>>Нет. Во-первых сборки тут совершенно не при чем. Во-вторых N = количеству загруженных на момент загрузки класса интерфейсов.


CS>Ясно. Т.е. ClassLoader как сущность "зарезана" сразу. Я правильно понял?


Да. В дотнете все несколько иначе устроено по сравнению с джавой, хотя домен загрузки в неявном виде присутствует.

AVK>>Если на этапе компиляции известен и тип и шаблон.


CS>Да конечно. Но это известно в 99% случаев. Т.е. на 99% эффективно.


Зависит от приложения. Но как только к примеру в сервере приложений переходим на динамический деплоймент, ни о каких 99% говорить уже не приходится. То же самое в дизайн-тайме.

CS>Для случаев когда не известно или когда это вредит принципиально (модульная независиомость, межязыковые интерфейсы)

CS>есть всякие разные полезные механизмы.

Ага, например СОМ. Беда только в том что это сильно усложняет поддержку компонентности.

CS>>>Тот же самый ATL/WTL построен как раз на принципах минимизации исп. vtbl.

AVK>>Я в курсе. ИМХО экономия на спичках.

CS>В тех облястях где мне приходится работать эти "спички" называются шведскими. Каждая по 6 дюймов.


Ну например замена WndProc на статический код разумна разве что только на каких нибудь мобильных устройствах. Win GUI давно не та область, где настолько критично быстродействие.

AVK>>
AVK>>class Base {}
AVK>>class C : Base, IA {}
AVK>>interface IA {}
AVK>>...
AVK>>Base b = new C();
AVK>>IA ia = (IA)b; // здесь компилятор отрезолвить интерфейс не может
AVK>>


CS>А для чего его резолвить если он не используется?


Почему не используется? Ну добавь в конец вызов какого нибудь метода IA.

CS>А если он используется то должен быть объявлен.


Кто объявлен? Интерфейс? Так он в примере объявлен. Просто компилятор не может знать что в итоге в программе будет запрос IA у класса С.

AVK>>А где гарантия что ты у класса вобще когда либо попросишь этот интерфейс? Или компилятор выполняет перемножение всех классов и всех интерфейсов и строит для всех валидных комбинаций таблицы?


CS>Зачем ему перемножать?


CS>IAnimal — это просто список сигнатур функций в compile time. В runtime это указатель на статическую таблицу адресов.


Но для каждого класса эта таблица будет своей!

CS>Получение (суть построение) такого списка ( таблицы адресов методов) для данного класса — тривиальная задача компилятора/компоновщика.


Но ты же не знаешь у какого класса какой интерфейс мы попросим. В результате тебе придется строить такие таблицы для всех валидных комбинаций классов и интерфейсов. Итого имея 100 интерфейсов и 100 классов, которые по сигнатуре к ним подходят, получим что нужно будет построить 10000 таких таблиц.

CS>>>в рантайм пустой (null) но присвоение устанавливает ему this плюс адрес на некую статическую таблицу построенную в

CS>>>compile time.
AVK>>Т.е. при динамической загрузке это работать не будет.

CS>Ты имеешь ввиду late binding в стиле IDispatch?

CS>Если да, то я могу точно также динамически построить эту таблицу например по списку экспорта DLL.

И получится дотнет, только тормознее .

CS>Давай я еще раз подчеркну основные фенечки:

CS>

CS>Polymorphism without Space Overhead
CS>Because polymorphism is provided externally to a class, it means that any class can be used polymorphically and also that there is no overhead of vtable pointers within a class. Most OOP languages, if not all, require a significant overhead to provide polymorphic behaviour.

CS>The only caveat is that the interface references are typically twice the width of an an ordinary reference ( technically this is not neccessarily the case, as I will explain below ). On the other hand the overhead of multiple interface implementation in other languages is considerably more significant.

CS>Polymorphism only when Needed
CS>Another advantage of the Heron interfaces approach, is that you don't need to incur any of the cost of run-time polymorphism, until when and if you explicitly require it. That cost includes the inability to inline functions, the performance hit of dynamic dispatch and the space overhead of function dispatch tables.


Ну собственно в дотнете все эти бенефиты присутствуют, притом побочных эффектов куда меньше.
... << RSDN@Home 1.1.4 beta 3 rev. 272>>
AVK Blog
Re[8]: Unintrusive Retroactive Polymorphism
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 06.01.05 12:06
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Не совсем: тамошнему поведению объяснение исключительно в пожелании так сделать, в стремлении к безопасности, т.е. предотвратить работу с несконструированным классом. Боксинг же — следствие оптимизации.


Какой оптимизации? Чего то я видимо недопонимаю. Автобоксинг никакого отношения к оптимизации не имеет. Это просто такая фишка, которую обычно делают вручную, когда хотят написать полиморфный код, использующий примитивные типы. К примеру держишь ты в памяти строку из БД. А там и int, и float, и string, и byte[]. И хранить это нужно в одной коллекции. Вот тут тебе и придется либо боксить, либо приводить все к void*. .NET всего лишь умеет это делать прозрачно. И оптимизация тут вобще никаким боком.
... << RSDN@Home 1.1.4 beta 3 rev. 272>>
AVK Blog
Re[8]: Unintrusive Retroactive Polymorphism
От: Павел Кузнецов  
Дата: 06.01.05 15:30
Оценка:
AndrewVK,

> ПК> Нет, вместо этого он строит "интерфейсную таблицу" только в момент, когда встретит приведение класса к интерфейсу.


> Т.е. либо в полиморфном коде это не работает, либо он делает это в рантайме.


Делается все это во время компиляции. Работает ли это "в полиморфном коде" — зависит от определения "полиморфного кода". Если речь идет о коде, работающем через ссылки на интерфейсы, то работать будет. Если о чем-то другом — тогда я тебя просто не понимаю.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.