假设我有一个名为Visitor的基类,它有2个子类Subscriber和NonSubscriber。
首先,访客是从NonSubscriber开始的,即
NonSubscriber mary = new NonSubscriber();
后来这个“mary”订阅了一些服务,我想把“mary”的类型改为Subscriber。
这样做的常规方法是什么?
答案 0 :(得分:6)
不能那样做。抱歉。 C#不是动态语言。
答案 1 :(得分:4)
您必须创建新的mary = new Subscriber();
并复制所有相关属性。
但更好的方法可能是对其进行不同的建模:给Visitor
订阅列表。空列表表示NonSubscriber。
答案 2 :(得分:4)
您无法进行此类转换。 您应该做的是将玛丽视为访客,当时间到来时,创建一个新的“订阅者”实例:
Visitor mary = new NonSubscriber();
// Do some Visitor operations
...
// Now mary is a Subscriber
mary = new Subscriber();
答案 3 :(得分:3)
您可以使用GOF设计模式 State 或策略来模拟此类行为。使用这些模式,在运行时似乎已经更改了对象的类。
答案 4 :(得分:1)
您无法在运行时更改变量的类型。您需要创建一个新实例。
mary = new Subscriber();
答案 5 :(得分:1)
您似乎遇到了一些设计问题。我认为重新设计代码会更好:
class Visitor
{
private bool isSubscriber = false;
public bool IsSubscriber
{
get { return isSubscriber; }
}
public void Subscribe()
{
// do some subscribing stuff
isSubscriber = true;
}
public void Unsubscribe()
{
// do some unsubscribing stuff
isSubscriber = false;
}
}
答案 6 :(得分:0)
创建一个Subscriber
构造函数,将NonSubscriber
对象作为参数,或者在NonSubscriber
对象上创建一个返回Subscriber
的方法,以节省您的编写多个地方的mappping代码。
答案 7 :(得分:0)
您似乎错误地将信息编码到类层次结构中。在这里使用不同于分类的模式会更有意义。例如,仅使用一个类(访问者,或者您可能将其命名为潜在订阅者,无论什么似乎合适)并对关于该对象所订阅的服务的信息进行编码,将动态变化的行为移动到“策略”模式或其他类似的背后。您的示例中的细节很少,但您可以在C#中执行的一项操作是创建一个“订阅者”属性,该属性会在更改属性状态时更改对象的行为。
这是一个人为的相关例子:
class Price
{
private int priceInCents;
private bool displayCents;
private Func<string> displayFunction;
public Price(int dollars, int cents)
{
priceInCents = dollars*100 + cents;
DisplayCents = true;
}
public bool DisplayCents
{
get { return displayCents; }
set
{
displayCents = value;
if (displayCents)
{
this.displayFunction = () => String.Format("{0}.{1}", priceInCents / 100, priceInCents % 100);
}
else
{
this.displayFunction = () => (priceInCents / 100).ToString();
}
}
}
public string ToString()
{
return this.displayFunction();
}
}
答案 8 :(得分:0)
public class User
{
public Subscription Subscription { get; set; }
public void HandleSubscription()
{
Subscription.Method();
}
}
public abstract class SubscriptionType
{
public abstract void Method();
}
public class NoSubscription : SubscriptionType
{
public override void Method()
{
// Do stuff for non subscribers
}
}
public class ServiceSubscription : SubscriptionType
{
public override void Method()
{
// Do stuff for service subscribers
}
}
public class Service2Subscription : SubscriptionType
{
public override void Method()
{
// Do stuff for service2 subscribers
}
}
认为代码解释了我的答案:)
答案 9 :(得分:0)
添加其他答案和评论,你确实可以将状态模式用于你的目的,它会是这样的:
public class MyProgram
{
public void Run()
{
Visitor v = new Visitor("Mary");
Debug.Assert(v.SubscriptionLinkText == "Join now");
v.IsSubscribed = true;
Debug.Assert(v.SubscriptionLinkText == "Today's special");
v.IsSubscribed = false;
Debug.Assert(v.SubscriptionLinkText == "Join now");
}
}
public class Visitor
{
public string Name { get; set; }
private bool _isSubscribed;
public bool IsSubscribed
{
get { return this._isSubscribed; }
set
{
if (value != this._isSubscribed)
{
this._isSubscribed = value;
this.OnSubscriptionChanged();
}
}
}
private SubscriptionBase _subscription;
public string SubscriptionLinkText
{
get { return this._subscription.LinkText; }
}
public Visitor(string name)
{
this.Name = name;
this._isSubscribed = false;
this.OnSubscriptionChanged();
}
private void OnSubscriptionChanged()
{
// Consider also defining an event and raising it here
this._subscription =
SubscriptionBase.GetSubscription(this.IsSubscribed);
}
}
abstract public class SubscriptionBase
{
// Factory method to get instance
static public SubscriptionBase GetSubscription(bool isSubscribed)
{
return isSubscribed ?
new Subscription() as SubscriptionBase
: new NoSubscription() as SubscriptionBase;
}
abstract public string LinkText { get; }
}
public class Subscription : SubscriptionBase
{
public override string LinkText
{
get { return "Today's Special"; }
}
}
public class NoSubscription : SubscriptionBase
{
public override string LinkText
{
get { return "Join now"; }
}
}