1

我正在制作第一个服务器客户端应用程序,我需要你的帮助。
客户端必须进行自我验证,然后才能玩一些游戏。
所以我有 USER 和 PLAYER 类:USER 包含所有注册用户,PLAYER 包含玩游戏的用户(有 PLAYER_GAME1、PLAYER_GAME2 等)。
在 USER 中,我有姓名、姓氏、id 等属性。
在 PLAYER 中,我需要有用户的属性以及点数、游戏时间等。

实际上:

     public class USER
{
        public string name, surname, ID, password, IP;
        WALLET wallet;
        bool login;
        datetime lastAccess;
        TcpClient socket;    
        Thread receiveMessages;//this receive message for log-in
        ...*other 30 proprieties*
     public USER(string n,string s,string _id,string pw)
    {
     *inizialize all variables*
    }
   }

   public class PLAYER
    {
      public USER user;
        Thread receiveMessages;
        int points;
        bool online;
        ...*other proprieties*

     public PLAYER(USER u)
     {
      user=u;
     *inizialize all variables*
     }
    }

所以为了得到名字我必须做:

PLAYER p= new PLAYER(new USER(...));
string name=p.user.name;

我认为更聪明的是让 PLAYER 成为 USER 的子类,当用户想要玩游戏时,我用 player 的特性“扩展”类用户,所以我需要这样做:

            public class USER
            {
                protected string name, surname, ID, password, IP;
                WALLET wallet;
                bool login;
                datetime lastAccess;
                TcpClient socket;    
                Thread receiveMessages;//this receive message for meneage the game
                ...*other 30 proprieties*

             public USER(string n,string s,string _id,string pw)
            {
             *inizialize all variables*
            }
           }

           public class PLAYER : USER
            {
                Thread receiveMessages;
                ...*other proprieties*

             public PLAYER():base()// here, what could i do?
             {
             *inizialize all PLAYER variables*
             }
            }

所以为了得到名字,我会这样做:

PLAYER p= new PLAYER();
p=exixtingUser;
string name=p.name;

我知道 SUBCLASS=MAINCLASS 是不可能的,那么我该怎么做呢?

4

2 回答 2

1

据我了解,您想Player根据信息创建一个角色User

如果我们的课程是:

public class User
{
    public Guid Id { get; private set; }
    public string Name { get; private set; }

    public User(Guid id, string name)
    {
        Id = id;
        Name = name;
    }
}

public class Player : User
{
    public TimeSpan TimeInGame { get; set; }

    public Player(User userInfo)
        : base(userInfo.Id, userInfo.Name)
    {

    }
}

这种构造函数的用法是:

var player = new Player(user);

您可以使用接受User信息的构造函数。您也可以编写扩展方法 .ToPlayer()或类似的东西。

我认为您应该阅读MSDN 上关于继承的文章,并继续阅读Constructors 文章


更新:

我已经理解您的问题,但不幸的是,没有简单的解决方案。您可以继续使用当前的解决方案,如果您的应用程序基于一个用户创建多个播放器,这将没问题。如果它是一对一的关系,你可以这样做:

public class User
{
    public Guid Id { get; private set; }
    public string Name { get; private set; }

    public User(User copyFrom)
    {
        Id = copyFrom.Id;
        Name = copyFrom.Name;
        // copy all the fields you need
    }
}

public class Player : User
{
    public TimeSpan TimeInGame { get; set; }

    public Player(User userInfo)
        : base(userInfo)
    {

    }
}

这个解决方案的主要问题是你必须自己复制它,没有任何自动化机制。你可以在这里找到一个类似的问题:

从派生类复制基类的内容

于 2014-12-27T15:01:12.233 回答
0

根据您的澄清要求,并且仅提供 VMAtm 的不错解决方案的扩展。

public class USER
{
   // changed to public getters so externally can be accessed
   // for read-only, but write access for USER instance or derived class (PLAYER)
   // QUESTIONABLE on public accessor on password
   public string name { get; protected set; }
   public string surname { get; protected set; }
   public string ID { get; protected set; }
   public string password { get; protected set; }
   public string IP { get; protected set; }

   WALLET wallet;
   bool login;
   datetime lastAccess;
   TcpClient socket;    
   // make this too protected AND available to player AND any others that make sense above
   protected Thread receiveMessages; //this receive message for meneage the game
   ...*other 30 proprieties*

   public USER(string nm, string sur, string _id, string pw)
   {
      name = nm;
      surname = sur;
      ID = _id;
      password = pw;

      InitUserVars();
   }

   private InitUserVars()
   {
      *inizialize all variables*
   }

}

public class PLAYER : USER
{
   // removed the Thread receiveMessages;
   // as it is avail on parent class  USER
   ...*other proprieties*

   // slightly different option, instead, call the "THIS" version of constructor
   public PLAYER(USER ui) : this(ui.name, ui.surname, ui.ID, ui.password )
   {  }

   // Now, pass same initializing parms to the USER base class so that all still runs the same.  
   public PLAYER(string nm, string sur, string _id, string pw) : base(nm, sur, _id, pw)
   {
      // by calling the "base" above, all default behaviors are handled first

      // Now, we can do whatever else specific to the PLAYER
      InitPlayerVars()
   }


   private InitPlayerVars()
   {
      *inizialize variables associated with PLAYER that is NOT part of USER baseclass*
   }
}

所以现在,在从用户扩展的播放器中使用相同的参数构造函数参数,您实际上可以跳转到直接使用参数创建播放器或间接绕过用户。

PLAYER p1 = new PLAYER( "name", "mr", 123, "mypassword" );

或作为结果使用用户的实例

USER u1 = new USER( "name", "mr", 123, "mypassword" );
PLAYER p1 = new PLAYER(u1);

这是否有助于为您阐明多个类实现的一些初始化?

于 2014-12-28T14:47:59.753 回答