In theory I love OOP (Object Oriented Programming) - up to a point. I love having properties. If I want to set one of my discrete I/O ports active then I like to be able to say something like DIO.State = Hi. Perfect right? It's at least better than, say: DIO_State = Hi. I think that's a little sloppy.
I'm not so hot on methods. Someone who is might try this: DIO.Assert(). Of course you'll also need DIO.Decline() (? I'm not fully sure on the opposite of assert at the moment. It's been a long day.) But then you also need something like DIO.Tristate() and DIO.UnTristate() and DIO.Toggle() which start to get a little hairy.
But why do you need those? Oh, that's because you made the State property 'protected' so that people can't set it directly. That's another tenant of OOP - don't let people touch things that they shouldn't. Instead provide 'safe' methods to change properties instead of letting people do it themselves (because they're EVIL! EEEEEVIL! They'd set your properties to invalid values and THEN what would you do?)
And then you go farther! Obviously since you save time when you use objects (another tenant of OOP) you decide to use them everywhere. So you've got relays too, and relays are kinda like DIO right? They go on and off - it's perfect! We'll just extend the DIO type to encompass relays too. So I can Assert() and Decline() relays to close and open them, and I can toggle them and I can Tristate() them... Ummm... wait... Relays don't tristate, do they? But it's a method of the relay object type so maybe they do? I forget...
Ok! Wait! I've got the answer! OOP also has this thing called inheritance where you can define an object type and then create more specific types from it (and from reading the tenants of OOP it seems this is good design practice). So I'll create an object with basic on/off functions and then extend that into DIO which will have tristate functions!
So now we have a parent type that I'll call a, ummm, 'Boolean' object. And Boolean will have a 'Open_Switch' method for the relays and a 'Close_Switch' method.. Or, hmmm. It won't make sense to 'Open_Switch' a DIO port, so we'll just have to call it something more general like 'Frob'. Yeah, 'Frob' will set the DIO high or close a relay and 'UnFrob' will do the opposite. And then 'XFrob' will toggle.
This is really coming together!
Of course that was all in my imagination and I made it worse than it had to be (a little anyhow). But it shows the problem with using OOP which is OVERusing it. Writing methods for toggling and setting a DIO port - sure go ahead. Extending a DIO type to relays? No, too far. Don't get sucked in to using things like inheritance just because it exists. A relay is not a specialized DIO port even if they have a couple of the same functions and properties!
PS - It seems Jeff Atwood agrees with me somewhat.
PPS - And again
Now I know he doesn't perfectly champion every single word in my post but I think we agree on general principles here.