我有这个子类实现我的接口,并且在满足合同方面没有错误。但是,当我尝试在子类的构造函数中设置当前会话时,我尝试将变量类型与返回的GetCurrentSession()类型进行比较时得到此编译时错误:
“无法将源类型IAPISession转换为目标类型FacebookSession”
好吗? Facebook是IAPISession ......对吧?在我看来,多态性是我的想法所以应该对这种比较感到满意。在这里不确定。
public class FacebookSession : IAPISession
{
private FacebookSession currentSession;
private FacebookSession()
{
currentSession = GetCurrentSession();
}
...more code
public IAPISession GetCurrentSession()
{
// my logic is here...whatever that may be
}
... more code
}
更新
这是我的实际界面:
public interface IAPISession
{
#region Properties
int SessionID { get; }
string UserID { get; }
bool SessionHasExpired { get; }
DateTime ExpirationDate { get; }
void LogOut(); // expires the session & sets SessionHasExpired
#endregion Properties
#region Methods
IAPISession GetCurrentSession();
#endregion Methods
}
此接口将用于我们的任何API包装器项目(例如FlickrSession等)
答案 0 :(得分:4)
是的,这需要一个明确的演员。您正在接收通用(接口)会话,但您想使用特定(Facebook)方法/字段。
您可能设想GetCurrentSession()
返回不同类型的IAPISession
的方案!
使用currentSession =
(FacebookSession)
GetCurrentSession();
在演员周围使用try
块
抓住这种可能性。我假设你的
如果不是,代码会感到困惑
一种FacebookSession
,所以你
需要处理这种情况。
只是为了澄清:
FacebookSession fbSess;
IAPISession genSess;
FacebookSession getFbSession() { ... return this; }
IAPISession getSession() { ... return this; }
genSess = getSession(); // legal
genSess = getFbSession(); // legal - implicit cast works as FacebookSession
// is always a kind of IAPISession
fbSess = getFbSession(); // legal
fbSess = getSession(); // ILLEGAL - not all IAPISession's will be
// kinds of FacebookSession
fbSess = (FacebookSession) getSession();
// legal, but might throw a class cast exception
// if it isn't a FacebookSession.
同样,
genSess = fbSess; // ok, implicit cast to generic type
fbSess = genSess; // ILLEGAL, it may not be a FacebookSession
fbSess = (FacebookSession) genSess;
// legal but can throw an exception
答案 1 :(得分:3)
虽然GetCurrentSession
实际上可能返回FacebookSession
,但返回类型为IAPISession
,并且没有从接口到实现该接口的任何类的隐式强制转换。
将GetCurrentSession
方法的返回类型更改为FacebookSession
或将currentSession
字段类型更改为IAPISession
(如果这样做有意义,则更改两者)。
答案 2 :(得分:1)
你需要反过来:
public class FacebookSession : IAPISession
{
private IAPISession currentSession;
private FacebookSession()
{
currentSession = GetCurrentSession();
}
...more code
public FacebookSession GetCurrentSession()
{
// my logic is here...whatever that may be
}
... more code
}
如果你想在类中使用特定的实现,那么我将在构造函数中实例化该类。然后在GetCurrentSession类中返回该实例。例如:
public class FacebookSession : IAPISession
{
private FacebookSession currentSession;
private FacebookSession()
{
currentSession = new FacebookSession();
}
...more code
public IAPISession GetCurrentSession()
{
return currentSession;
}
... more code
}
就像丹尼尔提到的那样,这已接近单身人士模式。查看它的实现here。请参阅.NET Optimized Code
答案 3 :(得分:0)
在C#中,除非存在定义的强制转换,否则无法使用更通用的类型(在您的情况下为IAPISession)转换为更具体的类型(FacebookSession)而不使用显式强制转换
想想在这种情况下会发生什么:
var flickrSession = new FlickrSession();
var iApiFlickrSession = flickrSession as IAPISession;
var faceBookSession = iApiFlickrSession;
您可以保证FacebookSession的实例也是IAPISession的实例,但您不能总是保证IAPISession的实例也是FacebookSession的实例。
在第二种情况下,编译器不知道该怎么做。
您可以尝试使用as运算符(在您的情况下可能会或可能不会)。如果转换失败,该值将为null:
currentSession = GetCurrentSession() as FacebookSession;
答案 4 :(得分:0)
当你想要这样做时,你必须明确:
private FacebookSession()
{
currentSession = (FacebookSession) GetCurrentSession();
}
请注意,GetCurrentSession()
返回的对象的异常实际上不是FacebookSession
。
更新:
您似乎对运行时发生的事情与编译时发生的事情感到困惑:
currentSession = GetCurrentSession();
这无法编译,因为虽然GetCurrentSession
返回的对象可能在运行时是FacebookSession
对象,但所有编译器都知道它是实现IAPISession
,可能有许多实现IAPISession
的非FacebookSeesion对象。
currentSession = (FacebookSession) GetCurrentSession();
在这里,您要告诉编译器,“相信我 - 当我们运行它时,它将成为一个FacebookSession对象。如果我要lyin',您可能会因为异常而崩溃!”
currentSession = (int) GetCurrentSession();
这不会编译。你试图说“相信我”等等等,但是编译器称你的虚张声势说“Baloney!IAPISession无法成为int
”