冒号和他的学生们(连载24)——对象封装 - 编程入门网
}
public Date getBirthday()
{
return birthday;
}
public void setBirthday(Date birthday)
{
this.birthday = birthday;
}
public boolean getSex()
{
return sex;
}
public void setSex(boolean sex)
{
this.sex = sex;
}
/** *//** 计算年龄,负数表示未知 */
public int computeAge()
{
if (birthday == null) return -1;
Calendar dob = Calendar.getInstance();
dob.setTime(birthday);
Calendar now = Calendar.getInstance();
int age = now.get(Calendar.YEAR) - dob.get(Calendar.YEAR);
if (now.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR))
--age;
return age;
}
}
冒号和他的学生们(连载24)——对象封装(4)时间:2011-07-03 BlogJava 郑晖冒号提问:“这段代码简单得勿需多言,请问它的信息隐藏做得如何?” 众人目不转睛地盯了好一阵,无人应答。 冒号突发惊人之语:“如果我说User所有的方法都违背了信息隐藏原则,你们相信吗?” 直直的眼睛全都变圆了。 引号忽然明白了:“记得书上曾说不能直接返回类的内部对象。GetBirthday返回Date类型的生日,用户可以在调用此方法后直接对生日进行操作。” “说得对极了!”冒号夸赞道,“如果一个方法返回了一个可变(mutable)域对象(field object)的引用,无异于前门紧闭而后门洞开。解决的方法是防御性复制(defensive copying),即返回一个clone的对象,以免授人以柄(handle)。” 逗号有些难以置信:“好像这类做法很普通啊。” 冒号耐心详解:“首先,请注意可变和引用两个条件,所有基本类型的域不是引用,因而是安全的,而Java中String之类非基本类由于是不可变的(immutable),也是安全的。同样,在C++和C#中的非基本类的值类型(value type)也不在此列。此外C++中申明了const的指针或引用返回值也能防止客户修改。其次,普通的做法不代表是正确的。事实上,恕我直言:普通的程序员是不合格的,合格的程序员是不普通的。最后,信息隐藏原则固然极其重要,但也不是金科玉律,在一定条件下也是允许的。比如仅作数据储存之用的类甚至可以开放所有的域成员,又比如不同类的对象共享同一引用。此外在一定范围之内为提高效率也可能采取变通之法,当然是在对用户晓以利害之后。” 问号举一反三:“同样道理,setBirthday也会导致信息泄漏。考虑到Date类型如此常用,Java是不是该引入一个不可变的日期类型呢?” 叹号喃喃自语:“getSex和setSex会有什么问题呢?boolean是基本类型啊。” 冒号提示:“考虑一下性别的可能性。” 叹号讶然道:“难不成还有不男不女型?” 众皆大笑。 冒号淡淡一笑:“不排除这种可能。更实际的情况是,有时性别是未知的。” 句号建议:“可以将小boolean换成大Boolean,多一个null值。” 冒号进一步指出:“如果想处理三种以上的可能性,可以采用char类型或String类型。总之这是实现细节,最好不要暴露给客户。因此不妨将getSex换成isMale和isFemale两个接口。” 引号细细玩味:“如果isMale和isFemale均返回false,那么性别不是保密就是中性了。至于性别用boolean、Boolean、char还是String来实现,用户是懵然不知的,这样比直接了当的getSex更隐蔽也更灵活。” 冒号揭开最后的答案:“方法computeAge的问题不 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |