关于TclOO日志Mixin类的两项技术问题咨询
TclOO混入类(Mixin Classes)相关问题解答
问题a:更直接获取具体类名称的方法
你当前通过解析[self call]结果获取类名的方式依赖调用栈结构,存在潜在兼容性问题。TclOO提供了专门的命令info object class,可以直接、可靠地获取当前对象所属的类名称:
set concls [info object class [self]]
替换后Mixin构造函数可修改为:
constructor {args} { set concls [info object class [self]] try { set log [::logger::servicecmd $concls] } trap {LOGGER NO_SUCH_SERVICE} {} { set log [::logger::init $concls] } if {[llength [self next]] > 0} { next {*}$args } }
info object class [self]直接返回实例所属类的完整命名空间名称,避免了解析调用栈的不确定性。
问题b:简化Mixin使用,仅需mixin声明无需额外调用
你的当前实现已经满足“仅需mixin声明、无需额外调用init”的需求——只要Mixin构造函数正确处理构造函数链(通过next传递参数),混入类后,目标类的构造函数执行时会自动触发Mixin的初始化逻辑。
可以进一步优化代码健壮性:
- 去掉
[self next]的长度检查,TclOO允许直接调用next {*}$args(即使后续无构造函数链也不会报错)
优化后的Mixin构造函数:
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 }
验证后的完整代码:
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 [info object class [self]] try { set log [::logger::servicecmd $concls] } trap {LOGGER NO_SUCH_SERVICE} {} { set log [::logger::init $concls] } 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'
内容的提问来源于stack exchange,提问作者Christopher Horler
相关产品推荐
相关产品推荐

