要创建一个包含除BASE之外的其他信息的类,我们需要从中继承还是组合
本文关键字:我们 组合 继承 信息 其他 一个 包含 创建 BASE | 更新日期: 2023-09-27 17:57:54
我有一个名为BluetoothDeviceInfo
的类,来自32英尺库,用于处理蓝牙相关的内容。
我已经创建了我的程序,并且成功了。然而,我需要在一个"更完整"的类中添加一些信息,比如说,也包含GPS信息的类。
因此,我所做的是创建一个新的类MyDeviceInfo
,并从BluetoothDeviceInfo
派生它,如下代码所示。
基本*(我无法控制)
namespace InTheHand.Net.Sockets
{
public class BluetoothDeviceInfo : IComparable
{
public BluetoothDeviceInfo(BluetoothAddress address);
public bool Authenticated { get; }
public ClassOfDevice ClassOfDevice { get; }
public bool Connected { get; }
public BluetoothAddress DeviceAddress { get; }
public string DeviceName { get; set; }
.
.
.
导出*
public class MyDeviceInfo : BluetoothDeviceInfo
{
private bool gpsSignal;
public MyDeviceInfo(BluetoothAddress address) : base(address)
{
gpsSignal = false;
}
#region Properties
public bool GpsSignal { get { return gpsSignal; } set { gpsSignal = value;}}
}
我用MyDeviceInfo
类型替换了代码中的所有BluetoothDeviceInfo
类型。
除了这一部分,一切似乎都正常
这种称为Client.DiscoverDevice()
的特定方法返回类型为BluetoothDeviceInfo
的可用蓝牙设备的列表。由于这是一个基类类型,所以我将它强制转换为派生类MyDeviceInfo
的变量是没有意义的,而且我无法通过这一点,因为我需要设备列表。尽管听起来不对,我还是试着用这个代码来转换它(显然不起作用)
IEnumerable<MyDeviceInfo> _discoveredCsaDevices = (IEnumerable<MyDeviceInfo>)cli.DiscoverDevices().Where(d => (d.DeviceName.StartsWith(...
由于这个逻辑不适合继承,我想到了组合。然而,这并不完全符合组合思路,例如对象Bird
可以具有Airplane
类型的飞行功能,但不是全部,因为我实际上需要我的驱动类包括BluetoothDeviceInfo
的所有功能。
我想了解这里的大局,以及做这样一件事的方法。
很高兴听到你对此的想法和指导。
干杯
试试这个:
IEnumerable<MyDeviceInfo> _discoveredCsaDevices = (cli.DiscoverDevices().Where(d => (d.DeviceName.StartsWith(...).Select (b => new MyDeviceInfo(b.DeviceAddress)).ToList();
您可能需要提供一个MyDeviceInfo
构造函数,该构造函数采用BluetoothDeviceInfo
并复制所有属性。
更新
然后代码变为:
public class MyDeviceInfo : BluetoothDeviceInfo
{
private bool gpsSignal;
MyDeviceInfo(BluetoothDeviceInfo btInfo)
{
this.Authenticated = btInfo.Authenticated;
this.ClassOfDevice = btInfo.ClassOfDevice;
this.Connected = btInfo.Connected;
this.DeviceAddress = btInfo.DeviceAddress;
this.DeviceName = btInfo.DeviceName;
}
public MyDeviceInfo(string address) : base(address)
{
gpsSignal = false;
}
public bool GpsSignal { get { return gpsSignal; } set { gpsSignal = value;}}
}
你这样使用它:
IEnumerable<MyDeviceInfo> _discoveredCsaDevices = (cli.DiscoverDevices().Where(d => (d.DeviceName.StartsWith(...).Select (b => new MyDeviceInfo(b)).ToList();
应用程序说明
在继承有效的范围内,使用它。看看内德·斯托亚诺夫的回答。只有当库类为sealed
时,才应使用下面的答案。
问题#1-库类是sealed
,不依赖于interface
,因此我不能用自己的类替换它
解决方案:无论如何都要制作一个接口。
public interface IMyDeviceInfo : IComparable
{
BluetoothDeviceInfo(BluetoothAddress address);
bool Authenticated { get; }
ClassOfDevice ClassOfDevice { get; }
bool Connected { get; }
BluetoothAddress DeviceAddress { get; }
string DeviceName { get; set; }
...
}
问题#2-如何在接口下填充库类
解决方案:制作一个适配器。
public class DeviceInfoAdapter : IMyDeviceInfo
{
private BluetoothDeviceInfo m_theRealStuff;
// Allow yourself to bypass the abstraction to
// get down to the real object, because it may
// just be unavoidable in some cases.
// You may also mark it [Obsolete] or comment it out
// until you encounter a real need for it.
internal BluetoothDeviceInfo TheRealStuff
{
get { return m_theRealStuff; }
}
// Constructor. If the real stuff has been created by someone else.
public DeviceInfoAdapter(BluetoothDeviceInfo theRealStuff)
{
m_theRealStuff = theRealStuff;
}
// Constructor. A knock-off copy of the real stuff constructor.
public DeviceInfoAdapter(BluetoothAddress address)
{
m_theRealStuff = new BluetoothDeviceInfo(address);
}
// Imitate all properties and methods on the real stuff.
public bool Authenticated
{
get
{
return m_theRealStuff.Authenticated;
}
}
// ...
// Basically, for every publicly-accessible method or property,
// you just call the real stuff.
}
问题3-如何添加额外的属性
解决方案:制作一个装饰器。
public interface IMyDeviceInfoExtra : IMyDeviceInfo
{
bool GpsSignal { get; set; }
}
public class MyDeviceInfoWithGps : IMyDeviceInfoExtra
{
private IMyDeviceInfo m_theRealStuff;
private bool m_gpsSignal;
public MyDeviceInfoWithGps(IMyDeviceInfo theRealStuff)
{
m_theRealStuff = theRealStuff;
}
// the same thing again ... lots of code duplications
// The only new member here
public bool GpsSignal
{
get { return m_gpsSignal; }
set { m_gpsSignal = value; }
}
}