今天跟dio友们讨论起属性表的实现,很多人刚开始是接触不到属性表的,有点懵,我就顺便总结了一下,以我的理解,可行的用法如下:
1、类内直接定义:
import console;
class me {
aa=123;
// 这里以@开头,按照..util.metaProperty()约定规则,直接创建属性表:
@..util.metaProperty(
sxid = {
_get =function(){
return "aa:" ++ owner.aa;
};
_set = function(v){
owner.aa = v*2
};
}
);
}
var t =me();
console.dump(t.sxid);
t.sxid=123;
console.log(t.sxid);
console.pause(true);
运行结果:
2、通过类内定义的私有变量创建属性表:
import console;
class me {
ctor(){
// 这里定义一个私有变量(名称可以随意),用于保存属性表内容:
var metaProperty = ..util.metaProperty(
sxid = {
_get =function(){
return "aa:" ++ this.aa;
}
_set = function(v){
this.aa = v*2
}
}
)
}
aa=123;
// 这里通过引用私有变量创建属性表:
@metaProperty;
}
var t =me()
console.dump(t.sxid)
t.sxid=123
console.log(t.sxid)
console.pause(true);
运行结果:
3、通过类内定义的公开变量创建属性表:
import console;
class me {
// 这里定义一个公开变量(名称可以随意),用于保存属性表内容:
metaProperty = ..util.metaProperty(
sxid = {
_get =function(){
return "aa:" ++ this.aa;
};
_set = function(v){
this.aa = v*2
};
}
);
aa=123;
// 这里通过引用公开变量创建属性表:
@this.metaProperty;
}
var t =me()
console.dump(t.sxid)
t.sxid=123
console.log(t.sxid)
console.pause(true);
运行结果:
注意:属性表一旦被定义,是不可修改的。
这里的公开变量 metaProperty ,一旦被引用创建属性表后,即使变量值被修改了,也不影响已经定义的属性表。
如:
import console; class me { metaProperty = ..util.metaProperty( sxid = { _get =function(){ return "aa:" ++ owner.aa; }; _set = function(v){ owner.aa = v*2 }; } ); aa=123; @this.metaProperty; } me.metaProperty = 456 // 这里修改类的属性表变量值 var t =me() t.metaProperty = 789 // 这里修改实例的属性表变量值 console.dump(t.sxid) //这里输出123。 t.sxid=123 // 这里检测属性表是否被修改。 console.log(t.sxid) //这里仍然输出246,证明原属性表仍在。 console.pause(true);
运行结果:
4、类外定义:
这种方法会让类看起来更整洁,属性表的定义与类的声明是分离的,维护起来也更容易。aardio官方基本都用这种方法。如果属性较多,推荐这种方法。如果属性较少,可以使用方法1直接定义。
import console;
class me {
aa=123;
// 这里创建属性表,内容为类外赋值。
@metaProperty;
}
// 类外给属性表内容赋值:
me.metaProperty = ..util.metaProperty(
sxid = {
_get =function(){
return "aa:" ++ owner.aa;
};
_set = function(v){
owner.aa = v*2;
};
};
)
var t =me()
console.dump(t.sxid)
t.sxid=123
console.log(t.sxid)
console.pause(true);
运行结果:
官方手册上将:me.metaProperty = ..util.metaProperty()
定义为:var me.metaProperty = ..util.metaProperty()
据我测试,会报警提示,不成功。
5、注意事项:
1、属性表是不可见的,console.dump(类实例) 的时候,是看不见属性表的存在的。
2、当省略 _get 时可以创建一个只写属性,而省略 _set 时可以创建一个只读属性。
3、使用下划线 _ 作为首字符的类成员是只读成员,即使定义了_set,在_set内修改其值也会出错,如:
import console;
class me {
_aa=123; // 定义一个只读变量
@..util.metaProperty(
sxid = {
_get =function(){
return "aa:" ++ owner._aa;
};
_set = function(v){
owner._aa = v*2 // 试图修改只读变量的值
};
}
);
}
var t =me();
console.dump(t.sxid);
t.sxid=123;
console.log(t.sxid);
console.pause(true);
运行结果如下,明确的提示“不能修改一个只读变量 '_aa' ”。
首先:错误行号 17 行:t.sxid=123; 试图给实例变量 sxid 赋值;导致下一步错误:
导致:错误行号 10 行:owner._aa = v*2 ;试图给只读变量 _aa 赋值;