2016-09-19 92 views
0

我有一個簡單的ObjectPool的實現。 ObjectPool包含一堆ObjectPoolObjects。 ObjectPoolObject是一個抽象類,它定義了兩種方法。我正在嘗試將一個對父池的引用添加到ObjectPoolObject類中。我通過使用奇怪的循環模板模式開始工作,但後來我無法從已經派生自ObjectPoolObject的類派生出來。 (即,手榴彈從繼承自ObjectPoolObject的子彈中繼承)...無法將類型`ObjectPool的<T> '爲'ObjectPool的<ObjectPoolObject>'

因此無論如何,父池由ObjectPoolObject持有,如下所示:ObjectPool m_parent ...但我似乎不能設置m_parent = this;在ObjectPool類中...看起來像我應該能夠。我不希望有強制轉換爲對象,然後轉換爲ObjectPool的..好像我應該安全地能夠做到這一點:

public abstract class ObjectPoolObject : MonoBehaviour { 
    public abstract void ObjectPool_Activate(); 
    public abstract void ObjectPool_Deactivate(); 

    public ObjectPool<ObjectPoolObject> m_pool; 
} 


public class ObjectPool<T> where T : ObjectPoolObject 
{ 
    public ObjectPool(CreateObjectDelegate creationMethod) 
    { 
     m_creationMethod = creationMethod; 
     T objectPoolObject = creationMethod(); 
     // this is the line that gives me error CS0030: Cannot convert type `ObjectPool<T>' to `ObjectPool<ObjectPoolObject>' 
     objectPoolObject.m_pool = this; 
    } 
} 

由於T:ObjectPoolObject我應該能夠做到這一點...

所有我需要的是爲ObjectPoolObject有一個參考它的父ObjectPool的......我怎麼能做到這一點?

編輯:

這是錯誤消息:

error CS0030: Cannot convert type ObjectPool<T> to ObjectPool<ObjectPoolObject>' 

但由於T:ObjectPoolObject現在看來似乎應該是能夠做到這一點。它就像它說的「不能將子類轉換爲父類...」T繼承自ObjectPoolObject ...因此T的ObjectPool類似於ObjectPoolObject的子類ObjectPool ... Liskov替換原則應該允許我投射一個T的ObjectPool到ObjectPoolObject的ObjectPool。

例如,我有子彈的ObjectPool的其中子彈從ObjectPoolObject繼承。我應該可以將它轉換爲ObjectPoolObjects的ObjectPool,考慮到ObjectPool中的所有元素都是ObjectPoolObjects .....編輯 - 我開始明白演員的問題是什麼......它很難解釋,哇。

EDIT2 - 定義使用接口的答案「在」對一般類型的關鍵字是這個問題的正確答案。然而!我已經決定這已經越過了「太複雜」的行,並決定從ObjectPoolObject中刪除m_pool字段。當你從一個對象池中獲取一個對象時,它就由你來記錄它來自哪個池並將其正確放回。 m_pool字段只是簡單地弄髒了我的系統,對我來說太合理了。

去除ObjectPool的的Genericism完全也是一個實用的解決方案,但它需要我投每個ObjectPool.Get調用的返回結果,我決定,我不想,要麼。

+0

沒有,只是因爲T是(或從繼承)ObjectpoolObject並不意味着ObjectPool的是(或從繼承)ObjectPool的 Shazi

+0

這是ObjectPool的其中T:ObjectPoolObject .... 我應該能夠將其轉換爲ObjectPool ... 我認爲你有句子的第二部分倒退。我是T是一個ObjectPoolObject ... –

+0

我不這麼認爲?您正在嘗試使用ObjectPool (其中T是或從ObjectPoolObject繼承的變量)分配m_pool(它是ObjectPool )。 問題不在於T是從ObjectPoolObject繼承的,但是ObjectPool ObjectPoolObject繼承自ObjectPool (因爲那就是你試圖分配m_pool時所假設的) – Shazi

回答

2

你需要看的協方差和逆變在C#作爲記錄here

總之 - 你需要聲明類爲

public class ObjectPool<**in** T> where T : ObjectPoolObject 
0

的問題是,雖然T還確實是從ObjectPoolObject繼承,居屋沒什麼閹ObjectPool的自ObjectPool的<ObjectPoolObject>做<牛逼>繼承。

例如,採取以下代碼:

public class Class1<T> where T : Class3, new() 
{ 
    public Class1() 
    { 
     Class3 variable1; 
     variable1 = new T(); // This works just fine T is or inherits from Class3 

     Class1<Class3> variable3; 
     variable3 = new Class1<Class2>(); // This will not work, while Class2 does indeed inherit from Class3, 
              // Class1<Class2> is still a different class from Class1<Class3> 
              // while their type parameters have an inheritance between them, they themselves do not. 

     Class1<Class3> variable2; 
     variable2 = new Class1<T>(); // And for just the same reason as stated above, this will not work either 
    } 
} 

做你想做什麼,我們將不得不作出一些更復雜(說實話,複雜並不總是一件好事)。但只是爲了它的緣故,看看這個:

public class AbstractObjectPool<T, T2> where T : AbstractObjectPool<T, T2> where T2 : ObjectPoolObject<T, T2> 
{ 
    public T m_pool; 
} 

public class ObjectPool<T> : AbstractObjectPool<ObjectPool<T>, T> where T : ObjectPoolObject<ObjectPool<T>, T> 
{ 
    public ObjectPool(Func<ObjectPool<T>> creationMethod) 
    { 
     ObjectPool<T> objectPoolObject = creationMethod(); 
     objectPoolObject.m_pool = this; 
    } 
} 

public abstract class ObjectPoolObject<T, T2> where T : AbstractObjectPool<T, T2> where T2 : ObjectPoolObject<T, T2> 
{ 

} 

但是,我不知道如果(你的情況),你就不會過得更好alltogeather跳繩仿製藥和聯合爲一個簡單的基類:

public class ObjectPool 
{ 
    public ObjectPool(Func<ObjectPoolObject> creationMethod) 
    { 
     ObjectPoolObject objectPoolObject = creationMethod(); 
     objectPoolObject.m_pool = this; 
    } 
} 

public abstract class ObjectPoolObject 
{ 
    public ObjectPool m_pool; 
} 
+0

嘿,謝謝你的回答。我以一種非常方便的方式在ObjectPool中使用泛型,我想我可以改變這種便利以獲得我想要的父參考... 您的答案基本歸結爲:「//這不會工作,而Class2確實繼承了Class3, // Class1 仍然是與Class1不同的類 //雖然它們的類型參數在它們之間有繼承關係,但它們本身不是。「 你能幫我理解爲什麼嗎? –

+0

我想我將不再使用ObjectPool類中的泛型... –

+1

至於原因:當編譯器將您的代碼用於Class1 和Class1 時,它會生成兩種不同的類型,它們不共享任何彼此之間的繼承(有點像如果你手動創建了兩個名爲Class1ForClass2和Class1ForClass3的類)。在這種情況下,很容易看出Class1ForClass3沒有理由可以轉換爲Class1ForClass2或從Class1ForClass2轉換。 但是這兩個類之間的代碼將由JIT共享,即相同的代碼,不同的類型。 – Kolichikov

3

您需要使用in修飾符(僅在接口和委託上允許)修改您的類型參數。

interface IObjectPool<in T> where T : ObjectPoolObject 
{ 

} 

class ObjectPoolObject 
{ 
    public IObjectPool<ObjectPoolObject> Pool { get; internal set; } 
} 

class ObjectPool<T> : IObjectPool<T> where T : ObjectPoolObject 
{ 
    public ObjectPool(Func<T> createObject) 
    { 
     T obj = createObject(); 
     obj.Pool = this; 
    } 
} 
+0

真棒!謝謝!我知道這是可行的。我需要「in」關鍵字,而不是「out」關鍵字,但是,因爲我需要以T作爲參數的接口的「Store」方法 –

相關問題