2009年11月20日 星期五

自我超越

這是我喜歡的自我(PolygonLoader)超越方式,比較單純,而上面(IResourceLoader)也不需要特別配合我修改。A story about inner class & private member.可以討論看看有沒有其他作法可以達到同樣目的。



故事是這樣的,wendy老鳥寫了兩個 class GamePlayer & IResourceLoader, IResourceLoader有一些基本resource check跟 load跟debug的功能,而我們這小咖的任務是base在 IResourceLoader的架構,作一個特製的PolygonLoader(),如下。
class PolygonLoader : public IResourceLoader {
public:
 void load(GamePlayer& p) {
  p.PolygunRESID = 128;  // Compiler error!!
 }
};
問題來了,PolygonLoader不是GamePlayer的朋友,上面error怎麼辦?


簡單的說法: wendy 你的class有bug,你看我這邊有error耶 ,應該把這member搬到public吧 !(瞬殺)


還好的說法: wendy 可不可以你麻煩幫忙在IResourceLoader修改,加一個GetResID(){return pGamePlayer.PolygunRESID}; or SetResID() 之類的東西呢? (但是用到IResourceLoader的部門可能都會面臨重新compiler module)。

其實透過inner class的技巧 wendy已經在GamePlayer為我們的需求開了條路。
class GamePlayer{
public:
 enum SpecialTypeClass {
  Mage = 0,
  Paladin ,
  War ,
  Shaman ,
  Thief,
  TalentNum
 };
 friend class IResourceLoader;
 template class PrivateAccessor;
 
 //GamePlayer(int classType);
 GamePlayer(SpecialTypeClass seed);

 void Attack();
 GamePlayer();GamePlayer& operator = (const GamePlayer&);
private:
 
 GamePlayer(const GamePlayer&);
 
 static const int NumTurns = 5;

 int PolygunRESID;
 
 SpecialTypeClass Talent;
 int scores[NumTurns];
};
在implement PolygonLoader時就可以透過實際implement PrivateAccessor 的方式達到修改Gampleyer private member的目的。
/////PolygonLoader.h//////
class PolygonLoader : public IResourceLoader {
public:
 void load(GamePlayer& player) ;
};
template<>
class GamePlayer::PrivateAccessor{
public:
 static int& ResID(GamePlayer& player){
  return player.PolygunRESID;
 }
};
/////PolygonLoader.cpp//////
typedef GamePlayer::PrivateAccessor Accessor;

void PolygonLoader::load(GamePlayer& player){
 //modify private member here!
 Accessor::ResID(player) = 1234;  
};
比較覺得可以討論的部分是,難道當Create一個class的時候,開個後門(PrivateAccess)是一個良好的習慣嗎?有沒有其他更好的作法可以盡量維持原架構不變,達到擴充的目的。

Reference link: 還是簡單點好

3 則留言:

  1. “但是用到IResourceLoader的部門可能都會面臨重新compiler module”
    我覺得這句話是關鍵

    "難道當Create一個class的時候,開個後門(PrivateAccess)是一個良好的習慣嗎?"
    所以我覺得是否定的

    回覆刪除
  2. 除了發現inner class跟private member的技巧以外,會提這篇是這個案例提供了我們"需求"。基本上我不是很喜歡這篇提到的設計。但是如何設計一個讓別人好用,擴充性強又不需要常修改的class,腦子裡沒有更好的作法。

    欠的意思是不是覺得也不必這麼刻意避開修正IResourceLoader?有需求就應該改。

    ps: 這篇對我還有個暗示,trace 別人的code debug時別太鐵齒,private member還是有可能因為某個public 的 inner class被其他人更動到的 XD

    回覆刪除
  3. 我的意思是 “但是用到IResourceLoader的部門可能都會面臨重新compiler module” 是一個很好的出發點,並且是這個範例所要解決的真正問題。

    回覆刪除