简体   繁体   中英

methods from inherited class passed to base class

I have a feeling I'm doing this wrong. I'm new to abstract classes and such and have been reading tutorials for a little bit, but I can't figure out how to apply it to my situation. I think that my design might be faulty but I can't think of another way to do it. My company makes a few different computers and I need to be able to monitor the battery information. Although getting the information is not the problem, figuring out how to send the different commands to the base class to do what i need it to do. Say I want to get my cell 1 voltage. On one unit the command is 0x0418, on another it is 0x453. So in my information class I run a test to see what the model is. I have a Base class called battery that has a bunch of variables that are standard for each battery (cell voltage, charge ic, charging current etc etc) I then decided it would be good to make individual classes for each of my units that extends Battery.

Now my design of the classes I think is spot on (could be wrong as I am not good at abstraction and polymorphism). I have a panel that in the end would display the information that I get from the BatteryInformation class. something like Battery1Cell1Label.Text = batteryInfo.GetCell1(1); Battery2Cell1Label = batteryInfo.GetCell1(2).

So in my base class I guess I need a GetValue(byte command) (since it is a Embedded controller command to get each different types of information.) Maybe i should stop talking and just post my code of what i have and tell you the error that I have.

battery.cs

public abstract class Battery<T> //not sure that the <T> is right
{
    public string Information { get; private set; }
    public float Cell1 { get; private set; }
    public float Cell2 { get; private set; }
    public float Cell3 { get; private set; }
    public float Cell4 { get; private set; }
    public int FCC { get; private set; }
    public bool ChargeIC { get; private set; }
    public int StartCharge { get; private set; }
    public int CurrentCharge { get; private set; }
    public bool Exists { get; private set; }

    protected internal void GetValue(byte command)
    {
        //Use Embedded controller to get said value
        //ECPort.ReadEC(command);
        //Testing Purposeses
        Console.WriteLine(command);
    }
}

Battery8800.cs

class Battery8800 : Battery<Battery8800>
{
    public Battery8800() : base()
    {

    }
    public void GetValue(BatteryCommands command)
    {
        base.GetValue((byte)command);
    }

    public enum BatteryCommands
    {
        Battery1VoltageHigh = 0x0402,
        Battery1VoltageLow = 0x0403,
        Batt1ChargeCurrentHigh = 0x0404,
        Batt1ChargeCurrentLow = 0x0405,
        Battery1MaxError = 0x0407,
        Battery1RSOC = 0x0409,
        Battery1FCCHigh = 0x040E,
        Battery1FCCLow = 0x040F,
        Battery1DCHigh = 0x0412,
        Battery1DCLow = 0x0413,
        Battery1Cell1High = 0x0418,
        Battery1Cell1Low = 0x0419,
        Battery1Cell2High = 0x041A,
        Battery1Cell2Low = 0x041B,
        Battery1Cell3High = 0x041C,
        Battery1Cell3Low = 0x041D,
        Battery1Cell4High = 0x041E,
        Battery1Cell4Low = 0x041F,
        PowerSource1 = 0x0420,
//many more commands for battery 2 etc etc
    }
}

BatteryInformation.cs

class BatteryInformation
{
    public Battery battery1; //error says it needs 1 type of argument
    public Battery battery2; //error says it needs 1 type of argument
    public BatteryInformation()
    {

        switch (UnitModel.GetModelEnum())
        {
            case UnitModel.DLIModel.DLI8300M:
                battery1 = new Battery8300();
                battery2 = new Battery8300();
                break;
            case UnitModel.DLIModel.DLI8400:
                battery1 = new Battery8400();
                battery2 = new Battery8400();
                break;
            case UnitModel.DLIModel.DLI8500:
                battery1 = new Battery8500();
                break;
            case UnitModel.DLIModel.DLI8500P:
                battery1 = new Battery8500P();
                break;
            case UnitModel.DLIModel.DLI8800:
                battery1 = new Battery8800();
                break;
            case UnitModel.DLIModel.DLI9200:
                battery1 = new Battery9200();
                break;
            default:
                break;
        }
        //for testing purposes
        battery1 = new Battery8800();
        battery1.DoThis(Battery8800.BatteryCommands.Batt1ChargeCurrentHigh);
    }
}

YEAH FOR DRAFT SAVING!!! the power just went out, and I didn't loose but 1 sentence!

so while my computer was turning back on I was thinking it might be better to do something like this in my battery panel class.

    //in my timer_tick event
    BatteryInformation.UpdateBatteries();
    battery1Cell1Label.Text = BatteryInformation.Battery1.Cell1.ToString();
    //etc etc

but i still need to get this working but am having a hard time figuring out how to do abstraction. Thank you for your time.

EDIT

I think i'm going about this the wrong way.

class Battery1_8400 : Battery
{
    public override bool Update()
    {
        //TODO finish
        Exists = GetValue((ushort)Commands.PowerSource) != 0xFF;
        if (Exists)
        {
            Cell1 = GetValue((ushort)Commands.Cell1Low, (ushort)Commands.Cell1High) / 1000.0f;
            Cell2 = GetValue((ushort)Commands.Cell2Low, (ushort)Commands.Cell2High) / 1000.0f;
            Cell3 = GetValue((ushort)Commands.Cell3Low, (ushort)Commands.Cell3High) / 1000.0f;
            FCC = GetValue((ushort)Commands.FCCLow, (ushort)Commands.FCCHigh);
            Voltage = GetValue((ushort)Commands.VoltageLow, (ushort)Commands.VoltageHigh);
            return true;
        }
        else
        {
            return false;
        }
    }
    private enum Commands
    {
        PowerSource = 0x0480,
        Charge = 0x0432,
        RSOC = 0x0734,
        DCLow = 0x0402,
        DCHigh = 0x0403,
        FCCLow = 0x0404,
        FCCHigh = 0x0405,
        MaxError = 0x0730,
        Cell1Low = 0x0778,
        Cell1High = 0x0779,
        Cell2Low = 0x077C,
        Cell2High = 0x077D,
        Cell3Low = 0x0780,
        Cell3High = 0x0781,
        VoltageLow = 0x0438,
        VoltageHigh = 0x0439,
        ChargeCurrentLow = 0x0728,
        ChargeCurrentHigh = 0x0729,
        ChargeIC = 0x1A03,
    }
}

I have 9 files that are ALL identical in terms of how the Update command works the difference is in the enum. The commands are slightly different per class. look at batter2_8400.cs 's enum

    private enum Commands
    {
        PowerSource = 0x0480,
        Charge = 0x04C2,
        RSOC = 0x0834,
        DCLow = 0x0492,
        DCHigh = 0x0493,
        FCCLow = 0x0494,
        FCCHigh = 0x0495,
        MaxError = 0x0830,
        Cell1Low = 0x0878,
        Cell1High = 0x0879,
        Cell2Low = 0x087C,
        Cell2High = 0x087D,
        Cell3Low = 0x0880,
        Cell3High = 0x0881,
        VoltageLow = 0x04C8,
        VoltageHigh = 0x04C9,
        ChargeCurrentLow = 0x0828,
        ChargeCurrentHigh = 0x0829,
        ChargeIC = 0x1A04,
    }

the update command is identical in that one as well as the other 7 files. Seems kinda bad design to me, but i'm stumped as to how I should do this. By the way this is what my classes look like after the one answer I was given and the few comments that was received.

your base class BatteryInformation should have abstract properties for each value you need to retrieve like so:

public abstract class BatteryInfo {
    // int should be replaced with the actual data type of the value
    public abstract int VoltageHigh { get; }
    public abstract int VoltageLow { get; }
    // etc. for each value you need
}

Then in your child class you implement each property

public class Battery8800 : BatteryInfo {
    public override int VoltageHigh {
        get {
          int value;
          // do code to retrieve value
          return value;
        }
    }
}

In addition, I would provide a method somewhere that your UI can consume that looks like the following:

 public IEnumerable<BatteryInfo> GetAllBatteryInfo() {
   // get each battery
 }

That way the UI does not need to worry about how the battery info is retrieved for each battery. That allows you to use one of the list or grid style controls to view the battery info.

In the end I think i figured out what I should do. It looks clean to me and seems to make sense. Maybe you can critique it?

public abstract class Battery
{
    public string Information { get; set; }
    public float Cell1 { get {return GetValue(Cell1Low, Cell1High) / 1000.0f;} }
    public float Cell2 { get {return GetValue(Cell2Low, Cell2High) / 1000.0f;} }
    public float Cell3 { get {return GetValue(Cell3Low, Cell3High) / 1000.0f;} }
    public float Cell4 { get {return GetValue(Cell4Low, Cell4High) / 1000.0f;} }
    public float Voltage { get {return GetValue(VoltageLow, VoltageHigh);} }
    public int DC { get {return GetValue(DCLow, DCHigh);} }
    public int FCC { get {return GetValue(FCCLow, FCCHigh);} }
    //public bool ChargeIC { get {return } }
    //public int StartCharge { get {return } }
    //public int CurrentCharge { get {return } }
    public bool Exists { get {return GetValue(PowerSource) != 0xFF} }
    public int FCCPercent { get {return ((FCC * 100) / DC);} }

    /// <summary>
    /// Gets a value depending on the Embedded controller
    /// </summary>
    /// <param name="low">The low byte command to process</param>
    /// <param name="high">The high byte command to process</param>
    /// <returns></returns>
    private int GetValue(ushort low, ushort high)
    {
        //Use Embedded controller to get said value
        //ECPort.ReadEC(command);
        //Testing Purposeses
        var lowValue = ECPort.ReadEC(low);
        var highValue = ECPort.ReadEC(high);
        return (int)((highValue << 8) + lowValue);
    }

    private int GetValue(ushort command)
    {
        return (int)ECPort.ReadEC(command);
    }

    public abstract ushort PowerSource {get;}
    public abstract ushort Charge{get;}
    public abstract ushort RSOC{get;}
    public abstract ushort DCLow{get;}
    public abstract ushort DCHigh{get;}
    public abstract ushort FCCLow{get;}
    public abstract ushort FCCHigh{get;}
    public abstract ushort MaxError{get;}
    public abstract ushort Cell1Low{get;}
    public abstract ushort Cell1High{get;}
    public abstract ushort Cell2Low{get;}
    public abstract ushort Cell2High{get;}
    public abstract ushort Cell3Low{get;}
    public abstract ushort Cell3High{get;}
    public abstract ushort Cell4Low { get; }
    public abstract ushort Cell4High { get; }
    public abstract ushort VoltageLow{get;}
    public abstract ushort VoltageHigh{get;}
    public abstract ushort ChargeCurrentLow{get;}
    public abstract ushort ChargeCurrentHigh{get;}
    public abstract ushort ChargeIC{get;}

}

then on my sub classes that inherit it an example would be this

class Battery1_8400 : Battery
{
    public override ushort PowerSource { get {return 0x0480;}}
    public override ushort Charge { get {return  0x0432;}}
    public override ushort RSOC { get {return  0x0734;}}
    public override ushort DCLow { get {return  0x0402;}}
    public override ushort DCHigh { get {return  0x0403;}}
    public override ushort FCCLow { get {return  0x0404;}}
    public override ushort FCCHigh { get {return  0x0405;}}
    public override ushort MaxError { get {return  0x0730;}}
    public override ushort Cell1Low { get {return  0x0778;}}
    public override ushort Cell1High { get {return  0x0779;}}
    public override ushort Cell2Low { get {return  0x077C;}}
    public override ushort Cell2High { get {return  0x077D;}}
    public override ushort Cell3Low { get {return  0x0780;}}
    public override ushort Cell3High { get {return  0x0781;}}
    public override ushort VoltageLow { get {return  0x0438;}}
    public override ushort VoltageHigh { get {return  0x0439;}}
    public override ushort ChargeCurrentLow { get {return  0x0728;}}
    public override ushort ChargeCurrentHigh { get {return  0x0729;}}
    public override ushort ChargeIC { get {return  0x1A03;}}
}

now all i have to do is edit the one file battery.cs if i need to make a change to it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM