Миксин ведения журнала TclOO

Я написал этот код (ниже), пытаясь узнать больше о классах примесей TclOO.

а. есть ли более прямой способ написать имя конкретного класса из конструктора миксина?

set concls [lindex [самостоятельный вызов] 0 end end-1]

б. есть ли способ упростить класс миксина, используя self, не требующий дополнительных вызовов (например, init), кроме mixin (как показано ниже) при его использовании? (перепроверено с TclOO: миксин регистратора классов, не ясно)

миксин ::demo::utils::LoggingMixin

package require TclOO
package require try
package require logger

namespace eval ::demo::utils {}
namespace eval ::demo::naming {}

::oo::class create ::demo::utils::LoggingMixin {
    variable log
    
    constructor {args} {
        set concls [lindex [self call] 0 end end-1]
        try {
            set log [::logger::servicecmd $concls]
        } trap {LOGGER NO_SUCH_SERVICE} {} {
            set log [::logger::init $concls]
        }

        # check for next
        if {[llength [self next]] > 0} {
            next {*}$args
        }
    }
}

::oo::class create ::demo::naming::GenericNaming {
    mixin ::demo::utils::LoggingMixin
    
    variable log
    
    constructor {args} {
        ${log}::info "hello world"
    }
}

::oo::class create ::demo::naming::NewNaming {
    mixin ::demo::utils::LoggingMixin
    
    variable log
    
    constructor {args} {
        ${log}::info "new world"
    }

}


::demo::naming::GenericNaming new

::demo::naming::NewNaming new

ожидаемый результат:

$ tclsh ./mixin.tcl  
[Sun Jun 04 21:39:22 BST 2023] [::demo::naming::GenericNaming] [info] 'hello world'
[Sun Jun 04 21:39:22 BST 2023] [::demo::naming::NewNaming] [info] 'new world'
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы получить класс создаваемого объекта, достаточно сделать это в конструкторе:

set concls [info object class [self]]

Вам не нужно перебирать аргументы (хорошо, так как это более подвержено ошибкам, когда есть сложные переадресации или new и/или create были переопределены).

Tcl 8.6 не требует от вас package require TclOO или package require try; в наши дни обе функции являются встроенными.


Я был бы склонен настроить миксин ведения журнала следующим образом:

oo::class create ::demo::utils::LoggingMixin {
    variable log
    
    constructor {args} {
        set concls [info object class [self]]
        try {
            set log [::logger::servicecmd $concls]
        } trap {LOGGER NO_SUCH_SERVICE} {} {
            set log [::logger::init $concls]
        }
        next {*}$args
    }

    # TODO: Add methods for other wanted logging levels
    method LogInfo args {
        tailcall ${log}::info {*}$args
    }
}

Потому что тогда подкласс может быть просто таким:

oo::class create LoggingDemo {
    mixin ::demo::utils::LoggingMixin
    constructor {args} {
        my LogInfo "new world"
    }
}

Или я мог бы даже сделать некоторые процедуры для дальнейшего улучшения синтаксиса:

    constructor {args} {
        set concls [info object class [self]]
        try {
            set log [::logger::servicecmd $concls]
        } trap {LOGGER NO_SUCH_SERVICE} {} {
            set log [::logger::init $concls]
        }
        proc logInfo args {
            variable log; # Need to be explicit with this
            tailcall ${log}::info {*}$args
        }
        next {*}$args
    }

Другой подход заключается в том, чтобы миксин предоставлял самоинициализирующиеся методы ведения журнала:

oo::class create ::demo::utils::LoggingMixin {
    variable LoggingMixinLog
    
    method GetLog {level} {
        if {![info exist LoggingMixinLog]} {
            set concls [info object class [self]]
            try {
                set LoggingMixinLog [::logger::servicecmd $concls]
            } trap {LOGGER NO_SUCH_SERVICE} {} {
                set LoggingMixinLog [::logger::init $concls]
            }
        }
        return ${LoggingMixinLog}::$level
    }

    method LogInfo args {
        tailcall [my GetLog info] {*}$args
    }
}

oo::class create LoggingDemo {
    mixin ::demo::utils::LoggingMixin
    constructor {args} {
        my LogInfo "new world"
    }
}

Это имеет то преимущество, что поддерживает смешивание с объектами или классами постфактум.


Если вы создаете обертки журналов, рекомендуется вызывать их с помощью tailcall или uplevel 1, чтобы текущий кадр стека был тем, который хочет сделать запись в журнале, а не маленьким вспомогательным методом/процедурой прокси.

на данный момент я ограничен TCL 8.5 (сторонняя упаковка) и TCLOO, который я скомпилировал - я не видел тега для этого. Мне любопытно узнать, почему было бы полезно иметь однострочные функции-оболочки поверх более обычного документированного интерфейса ${log}::info ...?

Christopher Horler 05.06.2023 20:58

для создания тега tcl-8.5 требуется 1500 реп, которых даже после многих лет бездействия у меня нет!

Christopher Horler 05.06.2023 21:01

Другие вопросы по теме