Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force derived class to implement interface

I am here today (like yesterday) with another weird interface question.

I have a class:

public class InputDevice<T> where T : Button {

    protected List<T> buttons = new List<T>();

    protected InputDevice() {
        //Only allow instanciation from within a derived class
    }
}

As you can see, this class cannot be instantiated.
A class that derives from it might be able to be instantiated.

This is a subclass:

public sealed class Keyboard : InputDevice<KeyboardButton> {

    public Keyboard() {
        buttons.Add(new KeyboardButton(KeyCode.A));
    }
}

So far so good.
Now I'd like all derivers of InputDevice<T> to provide a GetButton() method.
That method should take in the enum-Type of the Device's buttons as an argument.

For the Keyboard class it would look like this:

public KeyBoardButton GetButton(KeyCode Code) {
    //Retrieve button
}

For the Mouse : InputDevice<MouseButton> it would look like:

public MouseButton GetButton(MouseButtons Button) {
    //Retrieve button
}

Note: MouseButton (class) != MouseButtons (enum)

Each deriver of InputDevice(T) must implement that method.
But I don't want the InputDevice(T) itself to implement it because it doesn't know the enum-type of the Buttons (f.e. KeyCode).
It just knows the type of the Buttons, which is T.

  1. Solution

Adding the following interface to InputDevice(T)

public interface IInputDevice{
    void GetButton(System.Type);
}
  • Problem:

InputDevice(T) has to implement it, which it can not.
I do not know the return type T of InputDevice(T)

  1. Solution:

Adding the method manually in all derivers.

  • Problem:

Derivers are not guaranteed to provide the methods.


Do you have a solution for this? I got really confused while trying to sort this out.

like image 409
Noel Widmer Avatar asked Apr 28 '15 11:04

Noel Widmer


People also ask

Can derived class implement interface?

Essentially, because a derived class still is also all of its base classes, it already implements all of its base classes' interfaces. The designers of the language acknowledged this and there is no need to redeclare that a derived class is implementing interfaces that are implemented by its base classes.

Is it mandatory to implement abstract methods in c#?

An abstract method must be implemented in all non-abstract classes using the override keyword. After overriding, the abstract method is in the non-Abstract class. We can derive this class in another class, and again we can override the same abstract method with it.

Can you derive an interface from a base interface?

Interfaces can inherit from one or more interfaces. The derived interface inherits the members from its base interfaces. A class that implements a derived interface must implement all members in the derived interface, including all members of the derived interface's base interfaces.

What is abstract class in c#?

Abstract class: is a restricted class that cannot be used to create objects (to access it, it must be inherited from another class). Abstract method: can only be used in an abstract class, and it does not have a body. The body is provided by the derived class (inherited from).


1 Answers

You could make the base class abstract and change its definition to include the key code type:

public abstract class InputDevice<TButton, TEnum> where TButton : Button {
    public abstract TButton GetButton(TEnum Code);
}

Then you could define the derived classes like this:

public sealed class Keyboard : InputDevice<KeyboardButton, KeyCode> {
    public override KeyboardButton GetButton(KeyCode Code) {
        // implementation here...
    }
}
like image 144
Paolo Tedesco Avatar answered Sep 21 '22 03:09

Paolo Tedesco