![](/img/trans.png)
[英]Is it a better design to inherit from an abstract class or from an interface if the child classes have a common property?
[英]Downcasting failing from common interface/abstract class
我有兩個類-Expert和Farmer,它們都有一些共同的特征,因此實現了一個抽象類User。 用戶實現接口IUser。 在我的應用程序中,最初填寫了通用字段,但隨后用戶指示它們是否是專家/農民。
此時,我想將當前對象投射到“專家”或“農民”中,以填寫各個唯一的字段。 我當前的方法是聲明IUser user = new Farmer();
然后嘗試在適當的時間進行適當的投放: Farmer farmer = user as Farmer
或Expert expert = user as Expert
。 但是,強制轉換為Expert總是失敗,盡管它們都實現了相同的接口和抽象類。
User
抽象類中定義的函數createUser()
或createFarmer()
,或者僅實例化User
和Farmer
並在兩個字段中都填充初始字段,采用在拆分時間所需的任何實例,但這兩個都不是特別的優雅。 專家的定義:
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; }
}
謝謝!
您如何期望農民成為專家? 即使他們實現了相同的通用接口,它們是完全不同的。 特別是您的班級有一些不常見的成員:
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
級。
或者,您可以在抽象基類中引入一些工廠方法。 但是,這樣做的缺點是您的基類需要了解所有可能的子類型。 因此,引入新的子類會導致更改基類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.