要创建一个包含除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的所有功能。

我想了解这里的大局,以及做这样一件事的方法。

很高兴听到你对此的想法和指导。

干杯

要创建一个包含除BASE之外的其他信息的类,我们需要从中继承还是组合

试试这个:

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; }
    }
}