Автор Тема: Интерфейсы в Оберонах  (Прочитано 13697 раз)

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Интерфейсы в Оберонах
« : Апрель 17, 2012, 09:55:10 am »
Вчера весь вечер размышлял над этим сообщением:
http://oberspace.dyndns.org/index.php/topic,214.msg4710.html#msg4710

А почему бы и нет? Мне нравится идея интерфейсов, в том виде как ее высказал Madzi.

Какие у них плюсы и минусы?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #1 : Апрель 17, 2012, 03:03:16 pm »
Вчера весь вечер размышлял над этим сообщением:
http://oberspace.dyndns.org/index.php/topic,214.msg4710.html#msg4710

А почему бы и нет? Мне нравится идея интерфейсов, в том виде как ее высказал Madzi.

Какие у них плюсы и минусы?

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

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #2 : Апрель 17, 2012, 03:07:15 pm »
Вчера весь вечер размышлял над этим сообщением:
http://oberspace.dyndns.org/index.php/topic,214.msg4710.html#msg4710

А почему бы и нет? Мне нравится идея интерфейсов, в том виде как ее высказал Madzi.

Какие у них плюсы и минусы?

Дык, все хорошо у них. Из минусов только усложнение компилятора и усложнение проверки типа. Для труЪ оберонщиков этого достаточно, чтобы не включать эту возможность в язык (при том, что можно и без них, правда кода ручками писать больше, но для труЪ оберонщиков это никогда не было проблемой).
А вот в Go интерфейсы есть, а наследования интерфейсов нет. То есть никакого вообще нет. Ни множественного ни одинарного. Кода ручками в результате приходится писать сильно меньше.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #3 : Апрель 17, 2012, 03:25:14 pm »
А вот в Go интерфейсы есть, а наследования интерфейсов нет. То есть никакого вообще нет. Ни множественного ни одинарного. Кода ручками в результате приходится писать сильно меньше.

За счет чего меньше?

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #4 : Апрель 17, 2012, 04:12:28 pm »
А вот в Go интерфейсы есть, а наследования интерфейсов нет. То есть никакого вообще нет. Ни множественного ни одинарного. Кода ручками в результате приходится писать сильно меньше.

За счет чего меньше?
За счет того, что нет комбинаторного взрыва интерфейсов. Допустим у нас есть функции a, b, c. Какие-то функции хотят от типа аргумента чтобы он умел только a, а кто-то хочет только b. А кто-то и a и b одновременно. Итого получаем следующие сочетания которые могут потребоваться: a, b, c, ab, ac, bc, abc.

Если мы попробуем это дело оформить в виде интерфейсов скажем в джаве, то у нас получится что-то вот такое:
    interface A {void a();}
    interface B {void b();}
    interface C {void c();}
    interface AB extends A, B {}
    interface AC extends A, C {}
    interface CB extends C, B {}
    interface ABC extends AC, CB, AB {}
   
    class MyType implements ABC {
        void a() {}
        void b() {}
        void c() {}
    }

И это всего лишь три функции. Также можно добавить сюда необходимость явного разрешение имен функций в некоторых ЯП (по моему, в том же C# это нужно будет сделать, но могу ошибаться).

Причем все эти интерфейсы будут болтаться где-то около объявления типа, а не там где он непосредственно нужен. То есть предусловие на функцию будет где-то за километр от самой функции, вообще в другой либе, другом пакете и так далее. И если, не дай бог, писатель этого типа забыл скажем написать интерфейс AB, то все. Придется резко извращаться. То есть в либе у нас так:
    interface A {void a();}
    interface B {void b();}
    interface C {void c();}
    interface AC extends A, C {}
    interface CB extends C, B {}
    interface ABC extends AC, CB {}
   
    class MyType implements ABC {
        void a() {}
        void b() {}
        void c() {}
    }

А нам нужно такое:
void f1(ABC x) {x.a(); x.b(); x.c();}
void f2(AB xx) {x.a(); x.b();}

void run() {
    MyType t = new MyType();
    f1(t);
    f2(t);
}

Предется лепить враппер:
    interface AB extends A, B{}
    class Wrapper extends MyType implements AB {}

Но это прокатит только если мы сами создаем объекты нужного типа, если же к нам уже приезжают готовые MyType объекты, то все хуже. Придется это дело агрегировать.
    interface AB extends A, B{}
    class Wrapper2 implements AB, ABC {
        private MyType myobj;
        Wrapper2 (MyType obj){myobj = obj;}
        void a() {myobj.a();}
        void b() {myobj.b();}
        void c() {myobj.c();}
    }   

Ну, понятно что у меня тут в примерах код совсем игрушечный, отформатирован не по правилам (по правилам если оформить - строчек будет раза в три-четыре больше) и вообще наверняка я тут где-то зевнул и про всякие hashCode забыл и isEquals, clone и так далее. Так что можешь смело умножать на четыре объем кода. Кода которого в Go просто не будет. За не надобностью.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

Губанов Сергей Юрьевич

  • Hero Member
  • *****
  • Сообщений: 590
    • Просмотр профиля
    • Домашняя страница
Re: Интерфейсы в Оберонах
« Ответ #5 : Апрель 17, 2012, 04:20:32 pm »
А вот в Go интерфейсы есть, а наследования интерфейсов нет.
Если взять это на вооружение там, то вызов виртуальной процедуры будет чуток быстрее так как не надо будет делать лишнее приведение типов. Каждый "интерфейс" можно будет положить в отдельный массив как я сделал это раньше с делегатом. Пожалуй это даже лучше чем все предыдущие варианты...

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #6 : Апрель 17, 2012, 04:31:50 pm »
Ну, понятно что у меня тут в примерах код совсем игрушечный, отформатирован не по правилам (по правилам если оформить - строчек будет раза в три-четыре больше) и вообще наверняка я тут где-то зевнул и про всякие hashCode забыл и isEquals, clone и так далее. Так что можешь смело умножать на четыре объем кода. Кода которого в Go просто не будет. За не надобностью.

ИМХО пример надуманный. Если я и сталкивался с такой проблемой, то в чужом коде, где без причины наследовали при первой возможности. Возможно в жабе все так запущенно, но в C++ нет необходимости писать враппер для требуемого комбинаторного интерфейса, если нужные интерфейсы уже отнаследованы/имплементированы. Кроме того, вообще ситуации, когда "на вход" требуется один объект с более чем одним интерфейсом крайне редки в моей практике (возможно это специфика С++, где соответсвующие решения принято делать через шаблоны). Зато случаи, когда "на вход" требуется более одного аргумента с разными интерфейсами, а в точке вызова это оказывается один объект - довольно часто.
struct Interface1;
struct Interface2;

void f(Interface1&, Interface2&); // обычно нет смысла требовать одного объекта с поддержкой и Interface1 и Interface2. Можно придумать, что это надо какому-нибудь контейнеру - но, как я говорил, в С++ это делается через шаблоны
...
f(*this, *this); // вот такое встречается

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #7 : Апрель 17, 2012, 04:50:54 pm »
ИМХО пример надуманный. Если я и сталкивался с такой проблемой, то в чужом коде, где без причины наследовали при первой возможности.
Не, он не надуманный. Я сам пару раз в такое втыкался. Причем именно в С++. И по моим воспоминаниям там было еще больнее чем в жабе. Правда думаю из за того, что шаблоны в том проекте были под запретом.

Кроме того, вообще ситуации, когда "на вход" требуется один объект с более чем одним интерфейсом крайне редки в моей практике (возможно это специфика С++, где соответсвующие решения принято делать через шаблоны). Зато случаи, когда "на вход" требуется более одного аргумента с разными интерфейсами, а в точке вызова это оказывается один объект - довольно часто.
struct Interface1;
struct Interface2;

void f(Interface1&, Interface2&); // обычно нет смысла требовать одного объекта с поддержкой и Interface1 и Interface2. Можно придумать, что это надо какому-нибудь контейнеру - но, как я говорил, в С++ это делается через шаблоны
...
f(*this, *this); // вот такое встречается
Ну ты же понимаешь, что в Go не нужно и такого делать :-) То есть ничто не мешает потребовать от какого-то типа, чтобы он реализовывал нужное множество функций (причем сам интерфейс объявляется прямо перед функцией f которая на вход хочет именно это, то есть ровно там где это нужно) и все будет работать.

Подход в Go очень похож на typeclasses из Хаскеля и концепты C++ (которых пока нет).
// в каком-то библиотечном пакете
package foo

type Foo struct {}
func (self *Foo) a() {}
func (self *Foo) b() {}
func (self *Foo) c() {}

// а это уже в каком-то совершенно другом пакете который пишет совсем другой человек
package testit
import "foo"

type AB interface {
    a()
    b()
}

func f(ab AB) {
    ab.a()
    ab.b()
}

func doIt() {
    obj := foo.Foo{}
    f(obj)
}
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

Madzi

  • Jr. Member
  • **
  • Сообщений: 86
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #8 : Апрель 17, 2012, 06:19:31 pm »
За счет того, что нет комбинаторного взрыва интерфейсов. Допустим у нас есть функции a, b, c. Какие-то функции хотят от типа аргумента чтобы он умел только a, а кто-то хочет только b. А кто-то и a и b одновременно. Итого получаем следующие сочетания которые могут потребоваться: a, b, c, ab, ac, bc, abc.

... индусский код скипнут...

А почему нельзя напистаь так:
public interface A {
    public void a();
}

public interface B {
    public void b();
}

public class CAB implements A, B {
}

public class CA implements A {
}

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #9 : Апрель 17, 2012, 06:58:14 pm »
За счет того, что нет комбинаторного взрыва интерфейсов. Допустим у нас есть функции a, b, c. Какие-то функции хотят от типа аргумента чтобы он умел только a, а кто-то хочет только b. А кто-то и a и b одновременно. Итого получаем следующие сочетания которые могут потребоваться: a, b, c, ab, ac, bc, abc.

... индусский код скипнут...

А почему нельзя напистаь так:
public interface A {
    public void a();
}

public interface B {
    public void b();
}

public class CAB implements A, B {
}

public class CA implements A {
}
А ты допиши в свой код функцию которая хочет от аргумента что бы он умел и A и B, но при этом ничего не знает про класс CAB.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

Madzi

  • Jr. Member
  • **
  • Сообщений: 86
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #10 : Апрель 17, 2012, 07:19:13 pm »

А ты допиши в свой код функцию которая хочет от аргумента что бы он умел и A и B, но при этом ничего не знает про класс CAB.

public void foo (<T implements A. B> arg) {
}

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #11 : Апрель 17, 2012, 07:22:04 pm »

А ты допиши в свой код функцию которая хочет от аргумента что бы он умел и A и B, но при этом ничего не знает про класс CAB.

public void foo (<T implements A. B> arg) {
}
А теперь без дженериков. С обобщенкой наваять много чего можно. Или ты предлагаешь в Оберон еще и обобщенку притащить?
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #12 : Апрель 17, 2012, 07:36:00 pm »
Подход в Go очень похож на typeclasses из Хаскеля и концепты C++ (которых пока нет).

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

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #13 : Апрель 17, 2012, 07:37:38 pm »

А ты допиши в свой код функцию которая хочет от аргумента что бы он умел и A и B, но при этом ничего не знает про класс CAB.

public void foo (<T implements A. B> arg) {
}
Тем более что это не валидный с точки зрения java код.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Интерфейсы в Оберонах
« Ответ #14 : Апрель 17, 2012, 08:38:59 pm »
Подход в Go очень похож на typeclasses из Хаскеля и концепты C++ (которых пока нет).

Интересно, как они это реализовали. Т.е., в моем (наивном) представлении в точке вызова такой функции для каждого типа передаваемого объекта должен генериться какой-то обобщенный прокси (виртуальная таблица) со ссылками на методы конкретного объекта. Насколько это эффективно?
По моему, там тот же самый дескриптор типа с таблицей виртуальных функций. Либо как в ObjC, где вызов метода идет по имени.

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