How to implement many classes that have the same methods as others?

I am a developer who works mainly with embedded devices (programmed with C and build). My knowledge of C # and OOP is very limited (although I can fake my way when necessary). I have five devices that communicate with a PC via USB. The PC performs some calculations and sends the result to the device. The same calculations are performed for each device, but the calculations are performed differently. For each device, I have a C # Windows Forms application that does some work and sends data back and forth to the device. I am currently trying to combine five different applications into one so that we can easily make changes, easily add new devices and have a standard user interface. My problem is that I don’t know exactly how to do this, since I don’t know which device will be used before launch. I am trying to avoid a bunch of if statements, and I would like to be able to put each device in a separate file. Here is some psudo code of what I'm talking about.

class Device //This is what EVERY device can do { ... DoWork1(); DoWork2(); DoWork3(); ... } class Device1 { ... DoWork1(); //This is how the work is done for this device DoWork2(); DoWork3(); ... } class Device2 { ... DoWork1(); //This is how the work is done for this device (not the same way as Device1) DoWork2(); DoWork3(); } public partial class frmMain : Form { private (some kind of object or something) CurrentDevice; public frmMain() { ... //Determine what device (could be one of five) is currently being used CurrentDevice = (which device is currently being used) //Could be CurrentDevice = new Device1(); } } private void Button1_Click() { CurrentDevice.DoWork1(); //But this could be Device1.DoWork1() or Device2.DoWork1(), depending on what device is currently being used (which was determined in the frmMain constructor) } 

I'm not sure, but I think I can use the interface, or possibly inherit the Device1 class for the Device class and override the methods ... But I don't know how I would have one general way to say CurrentDevice.DoWork1 (), as CurrentDevice can be Device1 or Device2.

Any ideas would be highly appreciated. I am using Visual Studio 2008 with .NET 3.5 on Windows XP SP3 and Windows 7.

I hope I have described the problem well enough. If not, or if I did not mention something that I should, please let me know. I am new to stackoverflow and C #.

Thanks,

Michael

+6
source share
4 answers

At first I was a little confused, because in this case the computer does the calculations, and the devices get the result. So, I understand that you need different implementations of something on the PC, not the devices themselves.

The real trick here is not to use an interface or inheritance - you already understood that. The trick gets the right type of implementation, and you use the factory for this part.

But you also need to solve the issue of inheritance and interface.

Use inheritance only if this “something” really is part of a common, but also significant family. Inheritance must have a very strong "eat" element.

OTOH there may be many objects that could do the calculations, but you would not want to create a family. The composition is useful here. In order to inherit this, you need to have a common base class. Here you can use composition so that each object can use a common interface to allow the computer to perform calculations.

I suggest this approach.

You should have a link to a common, common interface, IDoCalculation or some one that defines the method signature, which will be called in the same way for any device.

Then you need to get a specific device implementation for this interface, which means that each device can have a different implementation. Create a class for each type of device / implementation.

Now the trick is to get the class you need without knowing what it is. To save hidden data again and make the method a generic call, you can create a parameterized Factory. This factory accepts a parameter that describes which device requires computing for the PC. Then he interprets this parameter and on the basis of this creates a specific class that implements IDoCalculation. It is back and everything is ready.

I leave this for you to figure out how these objects should be organized into different assemblies ...

 //Common interface public interface IDoCalculation { //Use whatever method signatures you need int DoCalculation(); } public class DeviceImplementation1 : IDoCalculation { #region IDoCalculation Members public int DoCalculation() { //Device 1 Specific code goes here } #endregion } public class DeviceImplementation2 : IDoCalculation { #region IDoCalculation Members public int DoCalculation() { //Device 2 Specific code goes here } #endregion } // A simple factory that does not require a lot of OOP understanding. public class DeviceCalculationFactory { //Return a correct implementor based on the device type passed in public IDoCalculation GetCalculationImplementationInstance(string devicetype) { switch (devicetype) { case "Device1": return new DeviceImplementation1(); case "Device2": return new DeviceImplementation2(); default: //TODO ??? return null; } } } // A simple client that calls the methods and then send the results public class DeviceManager { //To do the calculation, get an implementor for the correct device type from the factory - Presumably the PC knows the device of interest, example "Device1" public void DoTheCalculationThing(string deviceType) { DeviceCalculationFactory factory = new DeviceCalculationFactory(); IDoCalculation calculation = factory.GetCalculationImplementationInstance(deviceType); int result = calculation.DoCalculation(); // now send the result to the device } } 
+4
source

In your case, you basically define an inheritance hierarchy, which can either consist of an abstract base class and two derived types, or an interface with two of its developers. for instance

 public abstract class BaseDevice { public abstract void DoWork1(); } public class Device1 : BaseDevice { public override void DoWork1() { // provide implementation here } } // also create Device2 : BaseDevice and implement 

OR you can use interface definition

 public interface IDevice { void DoWork1(); } public class Device1 : IDevice { public void DoWork1() { // provide implementation } } 

Which methodology you choose is up to you. You might prefer an abstract base class if, for example, you would like to define some behavior or properties with implementations that were common throughout the hierarchy. With an abstract class, you can provide an implementation. The interface is an empty contract; you cannot provide any general behaviors, only determining which behaviors or properties may be present.

In any case, you will refer to instances of a more derived type through an abstract or interface base. Thus, you do not care what the type of implementation is, only what it can do (these are methods or properties).

Example:

  BaseDevice device1 = new Device1(); BaseDevice device2 = new Device2(); // maybe you have a list? List<BaseDevice> devices = new List<BaseDevice> { device1, device2 }; foreach (BaseDevice device in devices) { device.DoWork1(); // notice you don't care about the actual type, just the behavior } 
+8
source

You may be interested in looking at some design patterns for this. http://www.oodesign.com/

In particular, the abstract Factory and the template method. I think one of them may be what you are looking for. http://www.oodesign.com/abstract-factory-pattern.html
http://www.oodesign.com/template-method-pattern.html

As I understand it, you want to have a base class, then inherit the functions of the base class and define them in subclasses. One of these patterns is likely to work for your scenario.

+1
source

Anthony Pegram's answer is excellent, but you can take it one step further. It is understood that, although it seems that all your devices perform the same tasks, you may find that some of them do not actually perform all the tasks, while others perform even more.

In such cases, you may be tempted to change the interface to add another DoWork5 or DoWork6 and simply raise NotImplemented exceptions to types that do not have a specific behavior.

This is difficult for many reasons. I would suggest (if you find yourself in this position) to take a look at making your roles clear. You do this by creating interfaces that represent a specific role (or a set of behaviors --- related to the principle of interface segregation).

That way you can have IMediaPlayer with Play , Pause , Rewind and another IMediaRecorder using the Record method. This way you perform the appropriate roles on your specific classes.

NTN

0
source

Source: https://habr.com/ru/post/886937/


All Articles