注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

韩国恺的博客

hanguokai.com

 
 
 

日志

 
 

Dart 语言入门(四)——特殊的对象方法  

2012-11-24 14:24:41|  分类: Dart |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

更新日期:2012年11月24日


对象中除了实例方法、静态方法和 getter/setter 方法外,还有一些特殊的方法。比如,操作符重载可以让你自定义操作符的行为,noSuchMethod 可以让你动态处理一个未定义的方法调用。


一、操作符重载

Dart 支持很多操作符,见下表,大部分和其它语言一样,不用特别在意。操作符的优先级按从上到下的顺序逐渐降低。

 说明 操作符
 一元后缀和参数测试 expr++    expr--    ()    []    .    ?identifier
 一元前缀 -expr(负数)    !expr    ~expr(求补)    ++expr    --expr   
 乘法 *    /    %(求余)    ~/(求商)
 加法 +    -
 位移 <<    >>
 关系判断和类型测试 >=    >    <=    <    as(类型转换)    is(类型测试)    is!
 相等判断 ==    != 
 按位与 &
 按位异或 ^
 按位或 |
 逻辑与 &&
 逻辑或 ||
 条件判断 expr1 ? expr2 : expr3
 级联调用(cascade) ..
 赋值 =    *=    /=    ~/=    %=    +=    -=    <<=    >>=    &=    ^=    |= 


但不是所有操作符允许重载的。你可以重载下面这些操作符:

<, +, |, [], >, /, ^, []=,  <=, ~/, &, ~, >=, *, <<, ==, –, %, >>

比如,List 和 Map 就重载了 [][]=  操作符,如 list[0], map['one'] = 9,让你可以方便的获取和设置其中的元素。

一元减(负数)和二元减这两个操作符都是 - ,重载时 Dart 会根据参数的个数区分(分别是无参数和1个参数)。


操作符本质上和方法一样,只是方法名特殊。要重载操作符,只需要在方法名前加上 operator 关键字。例如,下面在向量类中重载了 + 操作符。

class Vector {
num x, y;
Vector(this.x, this.y);
operator +(Vector other) => new Vector(x + other.x, y + other.y);
}

注意,两个操作数的操作符(例如 a + b)总是在左边的对象上调用的。

操作符重载不应滥用,应该符合人们的表达习惯


二、Object 中的方法

Dart 中所有的对象都继承自 Object,因此 Object 中定义的方法就是在所有对象中通用的,你还可以覆盖他们实现自己的定义。


1. noSuchMethod 方法

noSuchMethod 是定义在 Object 中的方法,当调用了对象上(包括所有超类)一个不存在的方法时,noSuchMethod 就会被调用,默认实现是抛出一个 NoSuchMethodError 的错误。你可以在你的类中重新定义这个方法,覆盖默认的实现,这样就可以动态地实现一些未定义的方法。


在 noSuchMethod 方法中只有一个 InvocationMirror 类型参数,这个 InvocationMirror 包含了原始方法调用的所有信息,如方法名和参数。noSuchMethod 方法的返回值同样会作为原始方法调用的返回值。下面的示例代码动态地实现了一个未明确定义的 save 方法,如果实际调用的方法不是我们打算处理的方法就应该像默认行为那样抛出错误。

class T {
noSuchMethod(InvocationMirror msg){
if (msg.memberName != 'save') { // 判断方法名,这里我们只处理 save 方法
super.noSuchMethod(msg); // 调用默认实现,抛出 NoSuchMethodError
} else { // 完成实际的处理

print('call save');

}
}
}


main(){

new T().save();

}

注意,不仅仅是常规的方法可以被 noSuchMethod 拦截,字段和 getter/setter 也可以被 noSuchMethod 拦截,因为在 Dart 中方法、字段和 getter/setter 是统一的。访问一个字段(如 obj.x)其实就是调用一个 getter 方法,而 getter 方法只是一种特殊形式的方法。

InvocationMirror 包含如下字段和方法

 bool isAccessor 是否是一个getter或setter调用
 bool isGetter 是否是一个getter调用
 bool isMethod 是否是一个普通方法调用
 bool isSetter 是否是一个setter调用
 String memberName 调用的方法名/成员名
 Map namedArguments 命名参数
 List positionalArguments 位置参数
 invokeOn(Object receiver) 在提供的对象上继续调用

这里我们看到,getter/setter方法与普通方法被认为是不同的。另外,invokeOn 方法当前尚未实现。


2. 相等比较 ==

Dart 中对两个对象 x 和 y 的相等判断使用 == 操作符(相当于 Java 中的 equals 方法),规则如下:

  1. 如果 x 或 y 有一个是 null,返回 false;如果二者都是 null,返回 true。
  2. 调用左边 x 的 == 方法进行比较

所以,你在实现自己的 == 操作符时不需要再判断参数是否为 null 了(但在 Java 中需要你自己判断)。

Object 中 == 的默认实现是判断两个对象是否为同一个对象,即 identical(this, other) 。Dart 内置的 identical 函数相当于Java中的 == 。

如果你要覆盖 == 方法,那么你也应该覆盖 hashCode 方法以维护一致性。

class Vector {
num x, y;
Vector(this.x, this.y);


bool operator ==(other) {

if(other is Vector){

return x == other.x && y == other.y;

} else {

return false;

}

}
}


3. hashCode

Object 中有一个 getter 方法 hashCode,如 obj.hashCode 。这样所有的对象都有哈希值,子类可以覆盖这个方法。如果覆盖这个方法,那么也应该覆盖 == 方法。如果两个对象相等(==),那么他们必需有相同的 hashCode 。哈希值并不要求唯一,但应该被很好地分布。

在 Map 中,如果把对象作为 key,就会用到对象的 hashCode 。

  评论这张
 
阅读(1196)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018