声明和实现,是分开好?还是放在一起好?

原创 2006年05月18日 17:30:00
昨天开始学C#,强迫自己用C#写一个应用(当然是不是工作中急需的,只是练练手而已),发现在C#里,类的声明和实现必须放在一起,这真是#@¥×&×……
/// 日志记录器接口
interface ILogger {
void append(string msg);
};

/// 创建日志记录器实例的工厂
class LoggerFactory {
public static ILogger execute() {
//注意这里,由于声明和实现必须放在一起,所以
//不得不让Logger的使用者知道有LoggerFlatFile这个冬冬的存在

return new LoggerFlatFile();
}
};

/// ILogger的平面文件实现(如果声明和实现可以分开,本来可以让外界不知道它的存在)
class LoggerFlatFile : ILogger {
public void append(string msg) {
...
}
};
考虑一个这样的实现:我需要一个日志记录器,但不想让使用者知道它的实现细节(以后我也许会将它改成单例、也许会记到SQLServer数据库中、也许会打印到控制台),所以我设计了一个ILogger接口,既然有了接口,那么就必须有个工厂来创建实现这个接口的派生类实例,问题在于,由于工厂类的声明和实现必须写在一起,所以知道工厂类的人,也就知道了LoggerFlatFile这个具体类,本来我是想把这一点隐藏起来的。
现在,假定有一个程序员张三,他准备用ILogger来记录一些日志,从IDE的智能感知里,他一下子就发现了LoggerFlatFile这个类是派生自ILogger并实现了其接口的,立刻就兴高采烈地用了一句“ILogger logger = new LoggerFlatFile()”来创建了实例并满意地开始使用……由于他并未注意到Factory的存在,造成这一后果的原因,其实并不是因为他的粗心,而恰恰是编译器没有能预防住他构造派生类实例!
而另一个程序员李四,他事先查看了文档,知道要创建ILogger实例就必须用LoggerFactory的execute()这一静态方法,但是,有一天,他丢了钱包导致方寸大乱,在写一段新代码时,忘记了要用工厂,而写了能使编译顺利通过的new……这仍然不能怪他,只能怪编译器……而编译器会很负责任地说,它放过的代码是符合语法的,真正的罪魁祸首,应该是类的设计者!
如果是C++,我可以将LoggerFlatFile这个类的声明和实现都放在CPP文件里,H文件里只放ILogger和LoggerFactory的声明,而LoggerFactory::execute()的实现却是放在CPP文件里的……再退一步,如果我非要把这一切都放在H文件里,我还可以令LoggerFlatFile的构造函数为私有,同时令LoggerFactory成为它的友元。
再从工程的构建上看,只要一个H文件不变,不管它的CPP如何改变,所有引用了该H文件的CPP都不用再重新编译,在很慢的一些编译器上(比如Borland C++ Builder),节约了相当的时间。
就我目前所能看到的“将声明和实现放在一起”的唯一“好处”,似乎只是“维护起来方便”,但这难道不是本末倒置的吗?类的设计应该是方便使用者(就是我的同事甚至我自己),而不是方便设计者,要尽量让使用者少犯、不犯错误……而在DELPHI里,每个DFM文件都对应一个PAS文件,在ASP.NET里,每个ASPX文件都对应一个.CS文件,在VB里也是同样,为什么使用者都不觉得维护起来麻烦,单单要指摘CPP和H的分开呢?在现代IDE里,在声明和实现之间切换也就是一个快捷键或双击鼠标的事情,何来麻烦之说?(在我的VS2003里,声明和实现的切换是快捷键ALT+G)
隐藏实现细节,向来是软件设计的追求,typedef也是一种隐藏细节,命名常量替代魔数也是,类的封装、接口的设计等,都是隐藏细节,为什么我非得把声明和实现放在一起呢?
BTW:我的好友说这么多年来,还从来没有人抱怨过这个问题,言下之意,就是说只是我一个人在JJYY,绝对的是RPWT :)

C++中类的声明和类的实现分开

首先我们要实现确定一个点是否在园内的功能 所以我们需要两个类一个Point类,一个Circle类 首先我们要先创建一个项目,名为Test2(这是我的项目名字)这里不做过多的解释,使用vs应该都会创...

MediaInfo使用简介(新版本支持HEVC)

MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码)。他除了提供DLL之外,本身也提供GUI工具用于查看视频信息。我使用中发现,新版本的Media...

将模板类声明和实现分开

原文地址:http://www.cppblog.com/sToa/archive/2009/07/25/91125.html 1.声明部分 // Tpl.h #pragma once ...

不能将类模板的声明与实现分开写

今天用类模型实现一个linklist,开始是.h和.cpp将类模板的声明与实现分开写的,结果总是报错: 摆弄了半个小时都不知道为啥,结果一百度,原来类模板的声明与实现是不能够分开写的。《C++编...

c++ 模板 声明与实现分开编写(error LNK2001: unresolved external symbol...)

对于所有的喜欢把声明和定义分开放的C++er,在写模板时要把它俩放在一起一定感到十分郁闷,于是我本着非要棒打鸳鸯的倾向,找到了几种“棒”~   欢迎各位完善棒打鸳鸯技巧~ 1.在模板的声明文件(.h...

为什么不能将类模板的声明与类模板函数实现分开写?

定义一个类一般都是在头文件中进行类声明,在cpp文件中实现,但使用模板时应注意目前的C++编译器还无法分离编译,最好将实现代码和声明代码均放在头 文件中。如: test.h template c...

模板函数原型声明和定义实现必须放在一起

问题起因是我在一个.h文件中定义模版类,忘了在.cpp中定义函数时如何写(就是忘了 CLASS::show中的),然后顺便在.h中声明了个模板函数(函数原型),又在cpp中定义,结果在主函数中用时,出...

Java 求闰年 (细细品味if语句分开写和合到一起写得到的不一样的结果)

package cn.itcast.demoZuoYe_GuanQia3; /* * 关卡3 训练1 * 定义一个方法,去打印指定两个年份之间所有的闰年年份 如:将2000和20...

将XSD文件中分开的元素,合并在一起

需求 将源XML [code=XML]                

为什么要将成员函数的声明和定义分开

为什么将成员函数的声明和定义分开,直接使用合并的成员函数岂不是更加简洁而又方便?如: int print(){return weight;} 要说明这个问题,我们得先了解内联函数。 普通内联函数 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:声明和实现,是分开好?还是放在一起好?
举报原因:
原因补充:

(最多只允许输入30个字)