如何扩展类的功能?

时间:2014-05-11 23:48:05

标签: c#

这是一个简单的概念,我之前没有遇到任何麻烦,所以非常感谢帮助。

public partial class Player
{
    public string Name
    { get; private set; }

    public int Id
    { get; private set; }
}

public partial class ExtendedPlayer : Player
{
    public string Color = "";
}

public class MainProgram
{
    static void Main()
    {
        Player p = new Player();

        // The following creates a null object "ep":
        ExtendedPlayer ep = p as ExtendedPlayer;

        // For proof, NullReferenceException is thrown here:
        ep.Color = "red";
    }
}

我在SO上阅读的其他一些文章依次创建ep,然后手动为其分配p的所有值。这是不可能的,因为Player只是可读的。

我读过的另一个解决方案是将Player变为interface,但由于存在Player对象,我无法做到这一点。

P.S。在我的情况下,Player实际上是图书馆的一部分。我创建了库,因此我可以更改其属性,但我不希望属性可编辑。但是,如果这会产生问题,我可以改变它是偏的事实。

3 个答案:

答案 0 :(得分:3)

您可以创建一个Player的受保护构造函数来初始化值:

public class Player {
    // other stuff same as in your example...

    protected Player(string name, int id) {
        this.Name = name;
        this.Id = id;
    }
}

public class ExtendedPlayer : Player {
    public ExtendedPlayer(Player p) : base(p.Name, p.Id) { }
}

// in your Main method, you can create an ExtendedPlayer from a Player like so:

Player p = new Player();

ExtendedPlayer e = new ExtendedPlayer(p);

一件事:as运算符不会将对象从一种类型转换为另一种类型。相反,它试图将一个变量的值转换为不同的类型。类型必须兼容。您不能将任何类型转换为任何其他类型。您可以在此处和其他地方阅读有关投射的信息:http://msdn.microsoft.com/en-us/library/ms173105.aspx

另一件事:您需要某种方式来初始化Player类中的字段。就像现在一样,值将是默认值(字符串为null,int为0)。也许你有更多我们没有看到的代码,所以这可能不是问题。但是,请注意,初始化播放器的机制与派生类如何初始化属于基类Player的字段相关(如上面的代码所示)。

您需要问自己的问题是您希望将Player转换为ExtendedPlayer的原因。为什么不首先创建ExtendedPlayer?我认为你的模型可能没有经过深思熟虑,所以花点时间考虑一下你将Player转换成ExtendedPlayer时你真正要做的事情,也许这个问题就会消失。 / p>

答案 1 :(得分:1)

如果要动态地向类中添加功能/行为,则应该查看装饰器模式。 ExtendedPlayer的实现将是这样的:

public interface IPlayer
{
  string Name {get;}
  string Id {get;}
}

public class Player: IPlayer
{
    public string Id {get; private set;}
    public string Name {get; private set;}
    Player (string name, string id)
    {
        Name = name;
        Id = id;
    }
}

public class ExtendedPlayer: IPlayer
{
    private IPlayer  _player;
    public string Id {get { return _player.Id; }}
    public string Name {get { return _player.Name + ", " + Color; }}
    public string Color{ {get;set;}
    Player (IPlayer player, string color)
    {
        _player = player;
        Color = color;
    }
}

IPlayer player = new Player("12", "Video player");
player = new ExtendedPlayer(player, "red");
Console.WriteLine(player.Id);                      // prints 12
Console.WriteLine(player.Name);                    // prints Video player, red
Console.WriteLine(((ExtendedPlayer)player).Color); // prints red

答案 2 :(得分:0)

您无法从播放器升级到ExtendedPlayer。看起来你正在使用c# - 所以看看扩展方法。 http://msdn.microsoft.com/en-us/library/bb383977.aspx

我并不完全清楚你为什么不在main中创建一个ExtendedPlayer而不是Player类型。 ExtendedPlayer派生自Player,因此您无法将Player转换为ExtendedPlayer,但您可以将ExtendedPlayer转换为Player。