So, just saw on the wpilib repo that (for java) the interface versions of command and subsystem are being converted into abstract classes. While the depreciation of command and subsystem base dont really worry me, I am extremely worried about the removal of the Command and Subsystem interfaces. Because java does not support multiple inheritance with abstract classes, this chagr will break any code that relies on a subsystem or command inheritig from bolth an existing abstract class and Command/Subsystem, with no easy way to fix the issue without simply includeing Subsystem or Command in The parent class, a solution that will not work for everything. So, im just wonderin, how soud peogrammers in a position like me go about trying to rectify this breakig change when 2024 rolls around?
(PS: Im bad with tones so apologies if this sounds anything outher than purely inquisitive, it is not intended to be)
Can you give a concrete example of a use case where this change is problematic?
Lets say you have an Abstract device class that a subsystem like a drivetrain inherits from, not every device in necessarily a subsystem. But that subsystem, is a Device.
As you noted originally, we can solve such cases with composition instead of inheritance. Do you have any particular reasons you’re hesitant to use composition?
For much of BreakerLib specifically I built all of my clases on a similar Interfac → Abstract Class architecture to the original command based setup, so with enoug refactoring and intermediary classes i shuled be fine, for BreakerLib it just leads to haveig two classes that have the same fuchtionaliity, but are unable to inherit from eachouther, only there interface counterpart. Im more woried for uses where this is not an option, at least not without major reactors or problematic inheritance webs (which is rich coming from the person (me) who uses 7 level deep inheritancein some classes, but i digres).
In my opinion, “Subsystem” is a poor name for what that class/interface actually does in the command-based framework. Colloquially, a subsystem is a robot component. In command-based though, a subsystem is a mutual exclusion primitive for command scheduling. It’s commonly used to prevent two commands running simultaneously that touch the same hardware, but more generally it’s just categorizing commands that are incompatible with each other.
Fair enough, but why condense Subsystem and SubsystemBase into the same classes insed of simply restructuring it to make it more clear whet they do while still providing an interface to use. (Again, sorry if my tone comes across badly)
Sorry, but could you explain what you mean?
What case do you have in mind where you need to subclass both Device and Subsystem at once instead of having a subclass of one contain an instance of the other (or some third class contain an instance of both)?
I don’t know because I wasn’t paying attention to the refactor (I maintain wpilib/wpimath instead of command-based).
Fair enough tbh, also, thank you your for you contributions!
Somthing like a drivetrain that is bolth a subsystem, but also inherits from an abstract class like Device that, say…, privides system health data and logging, a fuction that uses acess to private or protected variables and methods. Furthermore, composition can lead to some some very repetitive and unclean code, even sometimes being somewhat more difficult to maintain (at least in my admittedly limited experience)
You still haven’t given a concrete reason why you would need multiple inheritance to do that. What code are you trying to avoid repeating?
You’re going to have to write at least some commented pseudocode to answer this question. Discussing this in the abstract is kind of pointless.
An example woud be something like BreakerGenericLoopedDevice, instead of simply inheritig from BreakerGenericDevice, it woud uave to practically copy the entirety of BreakerGenericDevice, and its abstract parent class BreakerSelfTestableBase, just to have the same fuctionaltiy, all without inheritig from them, so despite doug the same thing, a NreakerGenericLooped device woud only be able to inhert from the lowest level self test class. (Specific to me, but still an example)
Slightly bad take here, but I kind of agree. When I first saw the PR, I was under the impression that the abstract Subsystem/CommandBase classes were the ones being removed. It seems the only purpose of those classes at the moment is livewindow and implicit registration to the command scheduler.
Those are nice features to have, but it kinda fees like they shoud still be separate from their interfaces
Using default interface methods to fake multiple inheritance isn’t great, and Sendable does more than just LiveWindow registration.
For reference, I wrote those interfaces. They were abstract classes in the original command-based. Making them interfaces was a mistake (my bad), and has resulted in a lot of annoying warts for teams that want Sendable integration while providing basically no meaningful improvement in expressiveness or concision to anyone else.
Ofc, but you can allways implement Sendable in the inheriting class, like what we do in BreakerGenericLoopedDevice
Why reinvent the wheel? And why design your logging API to interact with the rest of your code through subclassing when it’s such a rigid feature (in Java especially)?