2015-06-13 15 views
8

Tôi đang cố gắng để có được vào C# generics và đã tạo ra một máy nhà nước với mô hình nhà nước và bây giờ tôi cố gắng refactor.C# generics, tham khảo chéo các lớp học cho mô hình nhà nước

Tôi có trạng thái có tham chiếu đến đối tượng đang hoạt động.

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

    protected T statefulObject; 

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

} 

và tôi có đối tượng có trạng thái, điều này phải có tham chiếu đến trạng thái hiện tại của nó.

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

    public T state; 

} 

Nhưng nó không hoạt động ("loại không thể được sử dụng làm thông số loại 't' theo loại hoặc phương pháp chung").

public class Monster : StatefulObject<MonsterState> { 

} 

public abstract class MonsterState : AbstractState<Monster> { 

} 

Đây có phải là có thể:

một cái gì đó như thế này Những gì tôi muốn đạt được là gì? Nếu nó không theo cách này, có cái nào khác không? Cám ơn.

+0

Bạn khai báo 'StatefulObject' như một loại chung (đoạn 2) và sử dụng nó như một loại không chung chung (đoạn mã 1)? –

Trả lời

3

Bạn có thể lạm dụng giao diện và phương sai để đạt được điều đó:

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) 
    { 
    } 
} 

Cho dù đó thực sự là một ý tưởng tốt là đáng ngờ, mã này có thể là quá khó hiểu.


Bạn cũng có thể đi với đơn giản (nhưng ít mạnh mẽ, đánh máy) Cách tiếp cận:

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) 
    { 
    } 
} 

này sẽ không đảm bảo bạn sẽ không thể chuyển nhượng, nói một PlayerState đến một Monster , bạn nên kiểm tra xem thời gian chạy.

+0

Một trong những hạn chế của thiết kế này là bạn có thể gán cho Monster bất kỳ trạng thái nào không bị ràng buộc rằng trạng thái là một MonsterState –

+0

@MarcCals có, tôi thực sự hiểu lầm mục tiêu của OP. Tôi viết lại câu trả lời. –

+0

@LucasTrzesniewski Nó hoạt động. Tôi sẽ cần một thời gian để xem thông qua điều này :) Đầu tiên trình biên dịch phàn nàn về trong và ngoài trong các giao diện và tôi đã phải đặt mục tiêu để. Net4.0 (Tôi đang làm việc với Unity). Cảm ơn :) – ElDuderino

Các vấn đề liên quan