Показать сообщение отдельно
  #1 (permalink)  
Старый 28.07.2013, 02:41
Профессор
Отправить личное сообщение для tenshi Посмотреть профиль Найти все сообщения от tenshi
 
Регистрация: 20.03.2008
Сообщений: 1,183

Jin: И снова о наследовании
Зацените крутую либу реализующую новый подход к организации кода)

Фичи:
1. множественное виртуальное наследование
2. прямой быстрый доступ к любому методу предка
3. автоматическое объявление классов и пространств имён
4. объявление методов и примешивание в произвольном порядке
5. автоматическое выявление конфликтов на уровне методов
6. типизированные свойства
7. глобально именуемые функции


Объявим простенький синглтон:

$jin.method( function URI_encode( text ){
    return encodeURIComponent( text )
})

$jin.method( function URI_decode( text ){
    return decodeURIComponent( text )
})


Данный код примерно эквивалентен следующему:

var URI = URI || {}

URI.encode = function URI_encode( text ){
    return encodeURIComponent( text )
}

URI.decode = function URI_decode( text ){
    return decodeURIComponent( text )
}


Как видно, мы избавились от необходимости дублировать имя функции при объявлении (что полезно при дебаге, но зачастую лениво), а также не беспокоимся о том, чтобы нужный неймспейс существовал до объявления методов. Символ подчёркивания, как видно, заменяется на точку. Кроме того двойное подчёркивание заменяется на ".prototype.", что будет продемонстрировано ниже.

Теперь создадим простейший класс:

$jin.mixin( '$jin_klass', 'Man' )
$jin.property( 'Man__name', String )


Тут мы примешали к пространству имён Man поведение "$jin_klass", что превращает "Man" в фабрику объектов. После чего определяем свойство "name", которое всегда является строкой. Инстанцирование происходит простым вызовом:

var Anonymous = Man()

При этом можно передать хэш со значениями свойств:

var John = Man({ name: 'John' })

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

Man({ age: 17 }) // Error!

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

Man().name( 'Bob' ).name() // 'Bob'

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

Man().name( 17 ).name() // '17' потому что String( 17 )

Если значение ещё не установлено, то функция типа вызывается без параметров, чтобы сгенерировать дефолтное значение.

Man().name() // '' потому что String()

Разумеется можно определять различные свои типы.

Наследование реализуется через примешивание:

$jin.property( 'Artist__sceneName', String )
$jin.mixin( '$jin_klass', 'Artist', 'Man' )

Man().sceneName() // ''


Примешивать и создавать методы можно опять же в произвольном порядке.

$jin.mixin( 'Artist', '$jin_klass', 'Man' )
$jin.property( 'Artist__pseudoName', String )

Man().sceneName() // ''


Чтобы каждый раз не примешивать $jin_class можно сразу его и вызывать:

$jin.class( 'Artist', 'Man' )

Иногда могут возникать конфликты имён:

$jin.property( 'Artist__name', String )

$jin.klass( 'Artist', 'Man' )
$jin.property( 'Man__name', String )

Man().name() // Error!


Чтобы решить его нужно явно указать, что один метод может перегружать другой, посредством добавления дополнительного параметра вначале (коих может быть и несколько):

$jin.property( 'Artist__name', String )

$jin.klass( 'Artist', 'Man' )
$jin.property( 'Artist__name', 'Man__name', String )

Man().name() // ''


Тут мы указали, что в случае конфликта между "Artist__name" и "Man__name" использовано будет последнее. $jin.method действует аналогично.

$jin.method( function Man__toString( ){
    return 'Man'
})
$jin.method( function Black__toString( ){
    return 'Black'
})

$jin.klass( 'Man', 'Black', 'ManInBlack' )
$jin.method( 'Man__toString', 'Black__toString', function ManInBlack__toString( ){
    return this.Man__toString() + ' in ' + this.Black__toString()
})

ManInBlack() + '' // Man in Black


Как видно доступ к перегруженным методам возможен через их полные имена.

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

Багрепорты и идеи приветствуются)
__________________
.ня

Последний раз редактировалось tenshi, 02.08.2013 в 23:45.
Ответить с цитированием