I have an interface with default parameters and I want to call the implementing method from within the implementing class (in addition to from outside it). I also want to use its default parameters.
However, if I just call the method by name I cannot use the default parameters because they are only defined in the interface.I could repeat the default specifications in the implementing method but that is not likely due to DRY and all that details(especially the fact that the compiler would not check that they actually match up with the interface's defaults!)
I solve this by introducing a member called _this
that is the same as this
except it is declared as the interface type. Then when I want to use default parameters, I call the method with _this
. Here is sample code:
public interface IMovable
{
// I define the default parameters in only one place
void Move(int direction = 90, int speed = 100);
}
public class Ball: IMovable
{
// Here is my pattern
private readonly IMovable _this;
public Ball()
{
// Here is my pattern
_this = this;
}
// I don't want to repeat the defaults from the interface here, e.g.
// public void Move(int direction = 90, int speed = 100)
public void Move(int direction, int speed)
{
// ...
}
public void Play()
{
// ...
//This would not compile
//Move();
// Now I can call "Move" using its defaults
_this.Move();
// ...
}
}
Is there anything wrong with this pattern or a way to solve the problem in a better way? (Incidentally, I think this is a flaw in the language that I have to do something like this)
EDIT: Not a dup of Why are C# 4 optional parameters defined on interface not enforced on implementing class? ... I am primarily asking how to work around this language quirk, not asking why it was designed that way
Default interface methods enable an API author to add methods to an interface in future versions without breaking source or binary compatibility with existing implementations of that interface. The feature enables C# to interoperate with APIs targeting Android (Java) and iOS (Swift), which support similar features.
The Interface Body Default methods are defined with the default modifier, and static methods with the static keyword. All abstract, default, and static methods in an interface are implicitly public , so you can omit the public modifier. In addition, an interface can contain constant declarations.
In most cases, a final class is the best thing you can create. If a user doesn't like your class, they can simply choose not to use it. However, if you're building up a hierarchy of objects you should introduce an interface for every class.
Read( ) is then overridden in a Note type that derives from Document . using System; interface IStorable { void Read( ); void Write( ); } // Simplify Document to implement only IStorable public class Document : IStorable { // the document constructor public Document(string s) { Console.
You have three options.
public interface IMovable
{
void Move(int direction, int speed);
}
public static MovableExtensions
{
public static void Move(this IMovable movable)
{
movable.Move(90, 100);
}
}
This way you do not have to repeat the defaults defined in the IMovable
interface, and the defaults for the interface and implementation can never go out of sync.
public class Ball : IMovable
{
void IMovable.Move(int direction, int speed)
{
}
}
public class Ball : IMovable
{
public void Move(int direction = 90, int speed = 100)
{
}
}
There could be two users of your code: one who uses only the IMovable
interface, and one who uses only the Ball
class. Arguably there could be an obscure scenario in which the defaults for moving an IMovable
should be different than the defaults for moving a Ball
, and neither user should have to care about the defaults they aren't looking at.
I concede this explanation is not very satisfying. If you want more info on why the language was designed this way, read the question and top answer Giorgi Nakeuri linked to in his comment on your question: Why are C# 4 optional parameters defined on interface not enforced on implementing class?
Then use explicit implementation, when you cast and call it as the interface you will get the interface defaults, when you call it with the class you will get the class defaults eg:
public class Ball : IMovable
{
//this uses the interface defaults
//notice how you dont need to define the default values again
//they are only specified once, in the interface definition
void IMovable.Move(int direction, int speed)
{
Debug.WriteLine(direction + "," + speed);
}
//now for the specific case of this class you can have your own defaults
//or none, just what ever fits your needs
public void Move(int direction = 20, int speed = 10)
{
Debug.WriteLine(direction + ","+ speed);
}
public void Play()
{
Debug.WriteLine("From interface");
((IMovable) this).Move();
Debug.WriteLine("From this class defaults");
Move();
}
}
And the output
From Interface
90, 100
From this class defaults
20, 10
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With