个人牢骚, 无知者无畏.
在操作系统API这个层面上, 使用C++, 其中的面向对象的最重要的元素还不是多态, 而是封装, 也就是绝缘.
Symbian在这个层面上远远不够,特别在它的UI框架中, 经常一个class N多长长的virtual 函数, 使得开发者无所适从,N多protected成员变量, 你说我派生自它,到底用还是不用了. 给赋个null行不行?
private 成员变量就算了, N多private成员函数, 放在头文件中就'碍眼", 又不让调用, 显把把您啦.
我估计symbian经常打破它的二进制兼容, 部分就是拜封装之故.
经常看到系统文件中
// not available before Release XXX
API这个层次留给后门, 给个万能接口也不错啊. 几个无类型的void*就可以了.
又有很多地方不够灵活, 例如最底层的CCoeControl, 是整个UI控件的基类, 提供了N多虚拟函数, 就是没有一个可以让程序员
自己使用的virtual 函数, 即有时候我需要一个vtable的slot,
例如 virtual void DoSth(int tag, void * p);
然后程序员就可以很简单的实现一个自定义的处理.
private/protected/public
也是随意胡乱设置.
举个例子,
CCoeControl中的成员变量
protected:
TPoint iPosition;
TSize iSize;
但是又提供了public的成员函数, 例如
IMPORT_C void SetExtent(const TPoint& aPosition,const TSize& aSize);
IMPORT_C void SetSize(const TSize& aSize);
IMPORT_C void SetPosition(const TPoint& aPosition);
IMPORT_C void SetRect(const TRect& aRect);
来操作这些, 因此你到底给个iPostion/iSize给我有什么意思? 作为派生类, 我到底是要调用public的成员函数, 还是直接使用
protected的成员变量? 你还不如给我个public的 int tag, 让我想放什么放什么.
有些封装有过于严格, 例如 CEikMenuPane, 表示一个菜单, 其中包括菜单项目 MenuItem 集合
提供了一个public成员函数
IMPORT_C void SetItemArray(CItemArray* aItemArray);
直接设置整个MenuItem数组, 但是就是没有一个可以读取这个数组的.
CItemArray* iItemArray; 的成员变量是private的,
可以Set , 没有Get 的class设计还真是少见.
我这个程序就要知道这个MenuItem的数组, 结果最终的方法是,
声明一个CStupidSymbianHacker,
然后在系统头文件中声明为友元, 然后通过这个CStupidSymbianHacker来得到这个数组.
CWindowGc也是这个德行.
有
public的
IMPORT_C virtual void UseFont(const CFont *aFont);
给DC设置字体, 就是没有一个函数可以得到当前设置的字体.
字体被设置成private的.
private: // Private data
CFbsFont *iFont;
CWsScreenDevice *iDevice;
};
也是"只能摸不能看"的角色.
还有就是图形程序基本上必须是APP类型(也就是DLL), 需要你覆盖N多函数, new出N个对象, 必须强制使用它的Doc/Model/View, 简直就是模式越多越高级, 我一个简单的对话框程序, 你让我Model什么? 而且EXE让你用了, DLL你又不允许静态数据存在. 典型的控制欲旺盛, 又控制不好, 你指这要那, 把爽全留给自己, 痛苦全给程序员.
自己发明了一套Description,
8位版本
TDesC8, TDes8, TPtr8, TPtrC8, TBuf8, TBufC8, HBufC8
16位unicode版本
TDesC16, TDes16, TPtr16, TPtrC16, TBuf16, TBufC16, HBufC16
Tchar版本的typedef
TDesC, TDes, TPtr, TPtrC, TBuf, TBufC, HBufC
十几个classes和typedef, 愣是提供不出一个可以自动递增的string, 强!
CActiveScheduler也是给程序员的接口太少.
最近派生一个Listbox, 那有些地方也是诡秘得很. 实在是痛苦.