Есть ли термин для этой концепции, и существует ли он в языке статической типизации? - PullRequest
6 голосов
/ 13 мая 2010

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

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

Я думаю, что хороший термин для обозначения «отраженный класс». Вы создаете преобразование, которое принимает класс и возвращает измененный в желаемом виде класс. Синхронизация - самый простой случай, но есть и другие: сделать класс неизменным [обернуть методы, чтобы они клонировали, мутировать клон и включить его в результат], сделать класс доступным только для чтения [при условии, что вы можете идентифицировать мутирующие методы], сделать класс похоже, что он работает с типом A вместо типа B и т. д.

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

Мне просто интересно, реализовано ли это на языке и как оно называется.

Ответы [ 4 ]

2 голосов
/ 26 мая 2010

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

class Synchronized<T> {
    Object invocation( Object ... args ) {
        synchronize( this ) {
            return original.invocation( args );
        } 
    }
}
...
Foo f;
Synchronized<Foo> f2;
f.bar();
f2.bar(); // would be valid for the type-system

, где invocation и original будут ключевыми словами для этой новой абстракции.

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

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

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

Может быть, посмотрите на эти документы (я еще не прочитал их все, но планирую):

В последнем реферате написано:

Мы обсуждаем точные преимущества и Затраты на наше расширение с точки зрения критерии введены и иллюстрируют полезность единообразно доступна прокси путем реализации метода будущего вызовы как безопасно, так и прозрачно.

, который был одним из ваших вопросов.

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

1 голос
/ 13 мая 2010
0 голосов
/ 12 декабря 2010

Python имеет декораторов , которые связаны с тем, о чем вы говорите.

0 голосов
/ 13 мая 2010

Не могли бы вы сделать это с помощью шаблонов? Это было бы немного хакерски, но что-то вроде:

#define LOCKED = true;
#define UNLOCKED = false;

template<bool lock>
void doStuff(){
    if(lock){
        // get lock
    }
    // other code
    if(lock){
        // release lock
    }
}
...