从常见接口/抽象类

时间:2017-08-30 06:03:29

标签: c# inheritance interface abstract-class downcast

我有两个类 - Expert和Farmer,它们共享一些共同特征,因此实现了一个抽象类User。用户实现了一个接口IUser。在我的应用程序中,最初填写了常用字段,然后用户指出他们是否是专家/农民。

此时,我想将当前对象转换为专家或农民,以填写单独的唯一字段。我目前的方法是声明IUser user = new Farmer();然后尝试在适当的时间适当地投射:Farmer farmer = user as FarmerExpert expert = user as Expert。但是,对专家的强制转换总是失败,尽管它们都实现了相同的接口和抽象类。

  1. 为什么这个演员会失败?
  2. 使用继承整齐地解决这个问题的正确方法是什么?显然,可以创建createUser()抽象类中定义的函数createFarmer()User,或者只是实例化UserFarmer并填充两者中的初始字段,在分时,需要采取任何一个实例,但这些都不是特别优雅。
  3. 专家的定义:

    public partial class Expert : User
        {
    
            public override Guid Id { get; set; }
            [StringLength(200)]
            public override string Name { get; set; }
            [Key]
            [StringLength(10)]
            public override string phone { get; set; }
            [StringLength(50)]
            public override string state { get; set; }
            [StringLength(50)]
            public override string district { get; set; }
            [StringLength(6)]
            public override string PIN { get; set; }
            public override double geolat { get; set; }
            public override double geolong { get; set; }
            public override int v { get; set; }
            public override int h { get; set; }
            public override string AzureImageURL { get; set; }
    
            //IParty properties
            public override string ServiceUrl { get; set; }
            public override string ChannelId { get; set; }
            public override string PartyChannelAccountId { get; set; }
            public override string PartyChannelAccountName { get; set; }
            public override string BotChannelAccountId { get; set; }
            public override string BotChannelAccountName { get; set; }
            public override string ConversationAccountId { get; set; }
            public override string ConversationAccountName { get; set; }
    
    
            //Expert specific properties
            public double price { get; set; }
            public int totalRating { get; set; }
            public int numberOfRating { get; set; }
            public string description { get; set; }
            public string languages { get; set; }
            double _sortIndex = double.Nan
        }
    

    农民的定义:

    public partial class Farmer : User, IVisualizable
        {
            //User override fields
            [Key]
            public override Guid Id { get; set; }
            [StringLength(200)]
            public override string Name { get; set; }
            [StringLength(10)]
            public override string phone { get; set; }
            [StringLength(50)]
            public override string state { get; set; }
            [StringLength(50)]
            public override string district { get; set; }
            [StringLength(6)]
            public override string PIN { get; set; }
            public override double geolat { get; set; }
            public override double geolong { get; set; }
            public override int v { get; set; }
            public override int h { get; set; }
            public override string AzureImageURL { get; set; }
    
            //IParty properties
            public override string ServiceUrl { get; set; }
            public override string ChannelId { get; set; }
            public override string PartyChannelAccountId { get; set; }
            public override string PartyChannelAccountName { get; set; }
            public override string BotChannelAccountId { get; set; }
            public override string BotChannelAccountName { get; set; }
            public override string ConversationAccountId { get; set; }
            public override string ConversationAccountName { get; set; }
    
            //Farmer specific properties
            [StringLength(12)]
            public string AadhaarNum { get; set; }
            public int cropId { get; set; }
            [StringLength(1)]
            public string acreage { get; set; }
    
            /// <summary>
            /// Constructor calling base - sets Guid of farmer
            /// </summary>
            public Farmer() : base()
            {
    
            }
    
        }
    

    用户定义:

    public abstract class User : IUser
        {
            public abstract Guid Id { get; set; }
            public abstract string Name { get; set; }
            public abstract string phone { get; set; }
            public abstract string state { get; set; }
            public abstract string district { get; set; }
            public abstract string PIN { get; set; }
            public abstract double geolat { get; set; }
            public abstract double geolong { get; set; }
            public abstract int v { get; set; }
            public abstract int h { get; set; }
            public abstract string AzureImageURL { get; set; }
            public abstract string ServiceUrl { get; set; }
            public abstract string ChannelId { get; set; }
            public abstract string PartyChannelAccountId { get; set; }
            public abstract string PartyChannelAccountName { get; set; }
            public abstract string BotChannelAccountId { get; set; }
            public abstract string BotChannelAccountName { get; set; }
            public abstract string ConversationAccountId { get; set; }
            public abstract string ConversationAccountName { get; set; }
    
            /// <summary>
            /// Creates a new User with a new Guid already set.
            /// </summary>
            public User()
            {
                Id = Guid.NewGuid();
            }
    
        }
    

    IUser的定义:

    public interface IUser : IParty
        {
            Guid Id { get; set; }
            string Name { get; set; }
            string state { get; set; }
            string district { get; set; }
            string PIN { get; set; }
            double geolat { get; set; }
            double geolong { get; set; }
            int v { get; set; }
            int h { get; set; }
            string AzureImageURL { get; set; }
    
        }
    

    谢谢!

1 个答案:

答案 0 :(得分:2)

您希望农民如何成为专家?即使 if 它们实现相同的通用接口,它们也完全不同。特别是你的课程有一些不常见的成员:

class Expert
{
    public string languages { get; set; }
}
class Farmer
{
    public string AadhaarNum { get; set; }
}

如何将languages转换为AadhaarNum?这是不可能的,因此没有自动演员。你必须创建一些自己的演员或转换,例如

var farmer = new Farmer(expert);

这假设您在两个类中都有一个复制构造函数:

class Farmer
{
    public Farmer(IUser user)
    {
        this.Name = user.Name;
        ...
        // also set the members that exist only on farmer
    }
}

和相应的Expert - 类。

另外,您可以在抽象基类中引入一些工厂方法。但是,这样做的缺点是您的基类需要知道所有可能的子类型。因此,引入新的子类会导致更改基类。