2015-06-13 5 views
8

के लिए क्रॉस रेफरेंसिंग कक्षाएं मैं सी # जेनेरिक में प्रवेश करने की कोशिश कर रहा हूं और राज्य पैटर्न के साथ एक राज्य मशीन बनाई है और अब मैं रिफैक्टर करने की कोशिश करता हूं।सी # जेनेरिक, राज्य पैटर्न

मेरे पास एक राज्य है, जिस पर यह उस वस्तु का संदर्भ है जिस पर यह काम कर रहा है।

public abstract class AbstractState<T> where T : StatefulObject { 

    protected T statefulObject; 

    public AbstractState(T statefulObject) { 
     this.statefulObject = statefulObject; 
    } 

} 

और मेरे पास ऑब्जेक्ट है जिसमें राज्य हैं, इसका वर्तमान स्थिति का संदर्भ होना चाहिए।

public abstract class StatefulObject<T> : MonoBehaviour where T : AbstractState<StatefulObject<T>> { 

    public T state; 

} 

लेकिन यह काम नहीं करता है ("प्रकार के रूप में सामान्य प्रकार या विधि में प्रकार पैरामीटर 'टी' नहीं किया जा सकता")।

public class Monster : StatefulObject<MonsterState> { 

} 

public abstract class MonsterState : AbstractState<Monster> { 

} 

यह संभव है:

कुछ इस तरह मैं क्या हासिल करना चाहते हैं? यदि यह इस तरह से नहीं है, तो क्या कोई और है? धन्यवाद।

+0

आप 'स्टेटफुल ऑब्जेक्ट' को सामान्य प्रकार (2 स्निपेट) के रूप में कैसे घोषित कर रहे हैं और इसे गैर-सामान्य प्रकार (पहला स्निपेट) के रूप में उपयोग कर रहे हैं? –

उत्तर

3

आप दुरुपयोग इंटरफेस और विचरण कि प्राप्त करने के लिए कर सकते हैं:

public interface IState<out TObject, in TState> 
    where TObject : IStatefulObject<TObject, TState> 
    where TState : IState<TObject, TState> 
{ 
} 

public interface IStatefulObject<in TObject, out TState> 
    where TObject : IStatefulObject<TObject, TState> 
    where TState : IState<TObject, TState> 
{ 
} 

public abstract class AbstractState<TObject> : IState<TObject, AbstractState<TObject>> 
    where TObject : IStatefulObject<TObject, AbstractState<TObject>> 
{ 
    protected TObject Object { get; private set; } 

    public AbstractState(TObject obj) 
    { 
     Object = obj; 
    } 
} 

public abstract class StatefulObject<TState> : IStatefulObject<StatefulObject<TState>, TState> 
    where TState : IState<StatefulObject<TState>, TState> 
{ 
    protected TState State { get; set; } 
} 

public class Monster : StatefulObject<MonsterState> 
{ 
    public Monster() 
    { 
     State = new IdleMonsterState(this); 
    } 
} 

public abstract class MonsterState : AbstractState<Monster> 
{ 
    protected MonsterState(Monster monster) 
     : base(monster) 
    { 
    } 
} 

public class IdleMonsterState : MonsterState 
{ 
    public IdleMonsterState(Monster monster) 
     : base(monster) 
    { 
    } 
} 

यह वास्तव में एक अच्छा विचार संदिग्ध है या नहीं, इस तरह के कोड भी भ्रमित हो सकता है।


तुम भी सरल (लेकिन कम दृढ़ता से टाइप) दृष्टिकोण के साथ जा सकते हैं:

public abstract class AbstractState 
{ 
} 

public abstract class StatefulObject 
{ 
} 

public abstract class AbstractState<TObject> : AbstractState 
    where TObject : StatefulObject 
{ 
    protected TObject Object { get; private set; } 

    public AbstractState(TObject obj) 
    { 
     Object = obj; 
    } 
} 

public abstract class StatefulObject<TState> : StatefulObject 
    where TState : AbstractState 
{ 
    protected TState State { get; set; } 
} 

public class Monster : StatefulObject<MonsterState> 
{ 
} 

public abstract class MonsterState : AbstractState<Monster> 
{ 
    protected MonsterState(Monster monster) 
     : base(monster) 
    { 
    } 
} 

इससे यह सुनिश्चित नहीं होगा आप आवंटित करने के लिए सक्षम नहीं होगा, एक एक Monster को PlayerState कहना , आपको रनटाइम पर जांच करनी चाहिए।

+0

इस डिज़ाइन की कमी में से एक यह है कि आप किसी राक्षस को असाइन कर सकते हैं किसी भी राज्य को बाध्य नहीं किया जाता है कि राज्य एक MonsterState –

+0

@MarcCals हां है, मैं वास्तव में ओपी के लक्ष्य को गलत समझता हूं। मैं जवाब दोबारा लिखता हूं। –

+0

@LucasTrzesniewski यह काम करता है। मुझे इसके माध्यम से देखने के लिए कुछ समय चाहिए :) पहले संकलक ने इंटरफेस में अंदर और बाहर शिकायत की और मुझे लक्ष्य को .NET4.0 (मैं एकता के साथ काम कर रहा हूं) पर सेट करना पड़ा। धन्यवाद :) – ElDuderino

संबंधित मुद्दे