问题
假设我试图将手机模型化为普通手机和PDA的组合。这是一种多重继承方案(手机是手机,而是 PDA)。由于C#不支持多重继承,因此这几乎需要某种组合。另外,让我们说我还有其他理由支持作曲。
我一直想知道:是否有任何工具可以自动生成所有不可避免的传递代码?
让我用一些实际的代码充实我的例子:
接口
public interface IPhone
{
public void MakeCall(int phoneNumber);
public void AnswerCall();
public void HangUp();
}
public interface IPda
{
public void SendEmail(string[] recipientList, string subject, string message);
public int LookUpContactPhoneNumber(string contactName);
public void SyncWithComputer();
}
实现:
public class Phone : IPhone
{
public void MakeCall(int phoneNumber) { // implementation }
public void AnswerCall() { // implementation }
public void HangUp() { // implementation }
}
public class Pda : IPda
{
public void SendEmail(string[] recipientList, string subject, string message) { // implementation }
public int LookUpContactPhoneNumber(string contactName) { // implementation }
public void SyncWithComputer() { // implementation }
}
CellPhone类
public class CellPhone : IPhone, IPda
{
private IPhone _phone;
private IPda _pda;
public CellPhone(IPhone phone, IPda pda)
{
_phone = phone;
_pda = pda;
}
public void MakeCall(int phoneNumber)
{
_phone.MakeCall(phoneNumber);
}
public void AnswerCall()
{
_phone.AnswerCall();
}
public void HangUp()
{
_phone.HangUp();
}
public void SendEmail(string[] recipientList, string subject, string message)
{
_pda.SendEmail(recipientList, subject, message);
}
public int LookUpContactPhoneNumber(string contactName)
{
return _pda.LookUpContactPhoneNumber(contactName);
}
public void SyncWithComputer()
{
_pda.SyncWithComputer();
}
}
编写CellPhone类既繁琐又容易出错:
所有这一课确实充当了Phone
和Pda
类的管道。实际上没有理由要求人工努力输入所有这些传递语句(如_phone.MakeCall(phoneNumber);
)。它只暴露了几个成员字段的公共接口。
问题
是否有一个工具(最好是免费的:))可以让我免于容易出错的编写传递方法的麻烦?我知道我可以使用VS自动生成存根,但这只能让我获得一半。
您能评价此功能的可行性和可取性吗?是否值得向微软提出添加此类代码生成的建议?如果我这样做,你会投票吗?如果没有,你有什么反对意见?
修改
每个人似乎都在说同样的话:为什么我不把_phone
和_pda
变成公共财产?我对此的反对意见是它违反了“最少知识原则”。我的CellPhone
课程的客户应该只做手机所做的事情,不应该处理哪些功能是Phone
功能以及哪些是Pda
功能。这会产生额外的依赖关系,并使CellPhone界面的功能不那么明显。
另外,不要只关注这个例子。如果我正在编写适配器怎么办?它可能包含几个只是传递的接口成员,但它也可能包含一些具有唯一实现的唯一成员。我相信在很多情况下,传递代码是好东西,我只是不喜欢写它。
答案 0 :(得分:17)
是的,您可以使用精彩的VS加载项ReSharper
生成方法从代码生成菜单中选择“generate delegating methods”选项(使用默认快捷方式的Alt-Insert)。
如果你有一个实现接口的类,包含一个实现相同接口的字段,R#将为你提供一个生成传递代码的选项。它也可以与任意数量的接口一起使用。
答案 1 :(得分:2)
之前我已经看过这个建议(不一定是Stack Overflow)。不久前。我相信作者创建了一个Connect问题,虽然我不知道它的状态。
建议的语法是以下之一:
public class CellPhone : IPhone, IPda
{
private readonly IPhone _phone implements IPhone;
private readonly IPda _pda : IPda;
// ...
}
答案 2 :(得分:1)
为之前提供的答案添加一些视觉效果和细节。
将接口添加到您希望成为包装类的类
class MyWebElement : IWebElement { }
点击完成并享受您的新课程
class MyWebElement : IWebElement
{
private IWebElement _webElementImplementation;
public IWebElement FindElement(By @by)
{
return _webElementImplementation.FindElement(@by);
}
public ReadOnlyCollection<IWebElement> FindElements(By @by)
{
return _webElementImplementation.FindElements(@by);
}
public void Clear()
{
_webElementImplementation.Clear();
}
public void SendKeys(string text)
{
_webElementImplementation.SendKeys(text);
}
public void Submit()
{
_webElementImplementation.Submit();
}
public void Click()
{
_webElementImplementation.Click();
}
public string GetAttribute(string attributeName)
{
return _webElementImplementation.GetAttribute(attributeName);
}
public string GetCssValue(string propertyName)
{
return _webElementImplementation.GetCssValue(propertyName);
}
public string TagName
{
get { return _webElementImplementation.TagName; }
}
public string Text
{
get { return _webElementImplementation.Text; }
}
public bool Enabled
{
get { return _webElementImplementation.Enabled; }
}
public bool Selected
{
get { return _webElementImplementation.Selected; }
}
public Point Location
{
get { return _webElementImplementation.Location; }
}
public Size Size
{
get { return _webElementImplementation.Size; }
}
public bool Displayed
{
get { return _webElementImplementation.Displayed; }
}
}
答案 3 :(得分:0)
您可能需要检查this article,它将进入C#中的伪多重继承版本。
答案 4 :(得分:-1)
有趣的问题。 CellPhone类是否真的可以依赖现有的具体IPhone类提供的IPhone方法的实现?或者,CellPhone更有可能需要一些支持这些方法的自定义代码吗?
查看你的代码(虽然我对你的要求不太了解)让我想写下这样的东西:
public class CellPhone
{
private Phone _phone;
private Pda _pda;
public CellPhone(Phone phone, Pda pda)
{
_phone = phone;
_pda = pda;
}
public IPhone getPhone()
{
return _phone;
}
public IPda getPda()
{
return _pda;
}
public void MakeCall(string contactName) {
int phoneNumber = _pda.LookUpContactPhoneNumber(contactName);
_phone.MakeCall(phoneNumber);
}
}
问题2:
我真的不喜欢自动生成的代码。即使机器生成它 - 并且没有错误 - 您仍将负责维护它。那些方法看起来很像噪音。