I have a base class, say named B. I have two derived classes, D1 and D2.
Looks like:
public abstract class B
{
public abstract void DoSomething();
}
public class D1 : B
{
public override void DoSomething() { ... }
}
public class D2 : B
{
public override void DoSomething() { ... }
}
Now, I created a new interface IDeepCopyable<T> which has one method Clone():
public interface IDeepCopyable<T>
{
T Clone();
}
I want to force each subclass too implement this interface with the base class (i.e. IDeepCopyable<B>.
If I try to leave B's declaration as-is but just inherit from ('implement' is a more accurate term?) IDeepCopyable<T>, such as:
public abstract class B : IDeepCopyable<B>
Then to implement it in the derived classes (either implicitly or explicitly), the compiler gives me an error message "B does not implement interface member IDeepCopyable<B>.Clone()".
I can, of course, create an abstract method whose name is identical to the interface's method's name, but I find that ugly. Why to redeclare the method?
Can I, in any way, leave that as wanted?
I see that VS2019 has an option "Implement interface abstractly" so I think that the answer is no, but A) I want to be sure. B) If so, is there a design concept behind this behavior, or is it just a bug in C# design?
Thanks in advance.
I can, of course, create an abstract method whose name is identical to the interface's method's name, but I find that ugly.
That's the way to go. Your base class implements the interface. Hence it has to fulfil it. It can do this by implementing the method concretely (which is not desired here) or the base class can force its inheritors to do so by declaring the method abstractly.
You say that's ugly, well I think it's just explicit.
Anyway, there's no way around this ;-)
Related
It could be a silly question, but I am learning, and I was just curious what's happening, today I was playing with few oops concepts and learning it in VS. I was again puzzled to see that we don't have to implement multiple interfaces same method into a derived class where ACTUALLY we "inherit" the interface, but in base class.
May I know how it works? My concern is, even though I do not "inherit" interface methods in base class, I use a method with same name. I also do not implement it in derived class.
Can somebody help me understand what's happening and how and why?
Class A
{
public void Display()
{
Console.Writeline("I am from A");
}
}
interface IA
{
void Display();
}
interface IB
{
void Display();
}
Class B : A, IA, IB
{
}
Class Final
{
static void Main()
{
B b = new B();
b.Display(); // displays class A Display method.
Console.Readline();
}
}
Although I can't speak for the language team, you can answer this question by posing the alternative solution.
You want to know why B is considered to implement the interface IA even though the required method definition is in base class A, which doesn't implement the interface. So, let's consider the opposite: B should not be considered to implement the interface because the base class' method wasn't written with that interface in mind.
This means that your code doesn't compile. Why doesn't it compile? Because B doesn't implement required member Display of interface IA.
To fix this, you'd add a method Display to class B. That fixes the interface implementation. However, you now have a new compilation problem: you'll see a warning "B.Display()' hides inherited member 'ConsoleApplication1.A.Display()'. Use the new keyword if hiding was intended."
This is because your A.Display wasn't overrideable - and you don't want to override it. You can implement a method to call base.Display() if you choose, but this is extra code to essentially do nothing, and it makes a mess of your inheritance since a new method is handled differently to an override. (If you write A x = new B(); x.Display(); then you'll actually call A.Display() directly, which could get messy as your code evolves and is an accident waiting to happen.)
Alternatively, you might implement an entirely new B.Display method. What you've also now done is hidden the method implemented in class A from anyone who might derive from B or create an instance of B. Using new to hide methods is rarely a recipe for an understandable object structure, and this would be no exception - all so that you can implement an interface cleanly.
So ultimately, I would imagine, this decision was made because the alternative is far too messy.
The reason is because the implementation is "implied" -- an implicit implementation of an interface.
Class A
{
public void Display()
{
Console.Writeline("I am from A");
}
}
interface IA
{
void Display();
}
interface IB
{
void Display();
}
Class B : A, IA, IB
{
void AI.Display() { Console.Writeline("I am from AI.Display"); }
}
Class Final
{
static void Main()
{
B b = new B();
b.Display(); // displays class A Display method.
(b as IB).Display(); // displays class A Display method.
(b as AI).Display(); // displays AI.Display
Console.Readline();
}
}
The above example now has an explicit implementation of the interface method display. Notice the slight variation in the method signature -- this is how you declare an explicit implementation, that is used specifically when the object is represented by the interface, in this case (b as AI).
Otherwise, if the method signature matches, it is used automatically (implicitly) as the method for the interface.
What's happening in your situation is that class B is satisfying the IA interface contract through the fact that its inheriting the appropriate IA method implementations from class A.
The way to look at it is this - an interface is a contract (it has no implementation) therefore it simply demands that any implementing class defines all the same members which it defines in the contract.
In your case you have 1 method in your interface Display, your class B is the only class implementing this interface and it doesn't explicitly define an implementation for Display (perhaps this is where your confusion is). However, it is inheriting from A which does define an implementation for it therefore B implements the interface by default.
Let's say I have an interface that many many distinct classes implement:
public interface IHaveObjects
{
object firstObject();
}
(Note: I can't make it an abstract base class as implementors of IHaveObjects may already have a base class.)
Now I want to add a new method to the interface, so that one implementer of the interface can have special behaviour for it. Ideally I would do something like this:
public interface IHaveObjects
{
object firstObject();
object firstObjectOrFallback()
{
return firstObject();
}
}
then go to that one implementor of the interface and give it the override:
public class ObjectHaverPlus : IHaveObjects
{
public override object IHaveObjects.firstObjectOrFallback()
{
return firstObject() ?? getDefault();
}
}
However it is forbidden in C# to provide a method body in an interface, and I would like to avoid going to every single implementer of IHaveObjects to drop in a definition of firstObjectOrFallback(). (Imagine if there are hundreds or thousands)
Is there a way to do this without lots of copy paste?
How about introducing a second interface which inherits from IHaveObjects.
Than you only have to change these classes, which need the new interface with the new method.
This looks like:
interface I1
{
void Method1();
}
interface I2 : I1
{
void Method2();
}
That's the problem with interfaces - they don't have any default implementation so any changes to them are breaking changes - i.e. code needs to be modified to work with new version of interface.
Since your implementations already have base classes on their own - you cannot turn it into abstract class, nor does C# have multiple class inheritance.
What you can do is to think - is it really a method on interface? Or could it be implemented as an extension method on interface (didn't try that but I suppose it will work just fine)?
If it is a method on interface and it should stay there - you may think of breaking this interface into two parts, second inheriting from the first (IHaveObjectsAndSupportDefault : IHaveObjects) and use this interface where default value is truly needed (like some other answers indicate).
I may have misunderstood your question, but why not use a second interface, something like:
public interface IHaveObjectsEnhanced
{
object FirstObjectOrFallback();
}
Then you could implement the first and second interface:
public class ObjectHaverPlus : IHaveObjects, IHaveObjectsEnhanced
{
public object FirstObject()
{
}
public object FirstObjectOrFallback()
{
return FirstObject() ?? GetDefault();
}
}
Suppose an Interface I has two methods. For example Method1() and Method2().
A class A Implements an Interface I.
Is it possible for class A to implement only Method1() and ignore Method2()?
I know as per rule class A has to write implementation of both methods. I am asking if there any way to violate this rule?
You can avoid implementing it (a valid scenario) but not ignore it altogether (a questionable scenario).
public interface IFoo
{
void A();
void B();
}
// This abstract class doesn't know what to do with B(), so it puts
// the onus on subclasses to perform the implementation.
public abstract class Bar : IFoo
{
public void A() { }
public abstract void B();
}
No, there's no such concept in C# of optional interface members. If A implements I, then it must provide some implementation for all of I's members, even if the implementation does nothing or only throws an exception.
public class A : I
{
public void Method1()
{
// Do nothing.
}
public void Method2()
{
throw new NotImplementedException();
}
}
From a design perspective, why would you want to do this anyway in a statically typed language? Furthermore, why not just have two interfaces?
public interface I1 { void Method1(); }
public interface I2 { void Method2(); }
With your interfaces coded like this, you can have classes that implement one interface or the other, or both, or neither. To me, this makes more sense anyway.
UPDATE 2018-06-13
The C# lang Git Hub has a proposal in progress for default interface methods. In short, the interface developer would be able to provide an implementation for a method or methods in the interface itself, and the developer using the interface on their class or struct would not have to implement those methods explicitly. Not exactly what the OP was asking about, but potentially useful.
You must implement all methods of the interfaces your class inherits from. There is no way around that. But you can use explicit interface implementation to hide the method.
That way a user doesn't see the method on a variable that has the class as type, but when he casts to the interface he can call the method.
class A : I
{
void I.Method2()
{
throw new NotSupportedException();
}
}
then
A a;
a.Method2(); //doesn't compile
I i = a;
i.Method2(); //works
If the class A is only an abstract base class, you can also use an abstract method to implement the interface, leaving the concrete implementation to the derived classes.
No, there's not.
But you can code :
public void Method2(){
throw new NotImplementedException();
}
That will inform the application that this method cannot be called from this instance.
Yes if I was a class, but No if it's an interface.
I'm trying to create a set of classes with different level of abstraction. I will use the Vector example here.
My goal is that the user of my classes can choose the level of abstraction to use i.e. they may or may not want to be using the more derived class.
interface IVector
{
Vector A();
}
interface ISparseVector : IVector
{
new SparseVector A();
}
Now, I implement the classes as such:
class Vector : IVector
{
public Vector A() { return new Vector(); }
}
class SparseVector : Vector,ISparseVector
{
public new SparseVector A() { return new SparseVector(); }
}
This is all fine and dandy. However, when the base class is abstract such as:
abstract class Vector : IVector
{
public abstract Vector A();
}
class SparseVector : Vector,ISparseVector
{
public SparseVector A() { return new SparseVector(); } // Hides abstract member.
}
I get a compile error saying that the derived method is hiding the abstract method in Vector. Any idea of how to get around this?
The feature you want is called "return type covariance", and it is not a feature of C#. Return type covariance is the feature where you can have a virtual method that return an Animal, and then you override that with a method that returns a Giraffe.
Doing so is typesafe and some languages do have this feature -- C++ for example -- but C# does not and we have no plans to add it. Your overriding method has to be marked override, and it has to match exactly -- in name, formal parameter types, and return type.
The reason is in your first example on the Vector class, you weren't specifying an access level for the A() method. This means it is a private method, which is the default. You could use the new keyword in the SparseVector class to get around this error.
For a start, you should look at this thread which specifies why you cannot have an abstract constructor.
Why can't I create an abstract constructor on an abstract C# class?
Then, you should put an abstract method in your Vector class that can actually be overridden to provide implementation, as abstract methods are supposed to be.
You can't mix abstract and interface methods the way you're trying. If you were to declare 'Vector' abstract and override the implementation of A(), you'd be overriding 'Vector A()' from your abstract class, but that wouldn't implement the interface ISparseVector.Vector, which has a return type of ISparseVector.
Your use-case doesn't appear to require that 'Vector' be abstract.
I am working on a project, and I have a generic abstract type that takes a type parameter that is itself derived from the abstract type. If you want to know why I would do this, please see this question.
I have run into an interesting problem with overloading a method in a derived class that is defined in the abstract class. Here is a code sample:
public abstract class AbstractConverter<T, U>
where U : AbstractConvertible
where T : AbstractConverter<T, U>
{
public abstract T Convert(U convertible);
}
public class DerivedConvertibleConverter : AbstractConverter<DerivedConvertibleConverter, DerivedConvertible>
{
public DerivedConvertibleConverter(DerivedConvertible convertible)
{
Convert(convertible);
}
public override DerivedConvertibleConverter Convert(DerivedConvertible convertible)
{
//This will not be called
System.Console.WriteLine("Called the most derived method");
return this;
}
public DerivedConvertibleConverter Convert(Convertible convertible)
{
System.Console.WriteLine("Called the least derived method");
return this;
}
}
public abstract class AbstractConvertible {}
public class Convertible : AbstractConvertible {}
public class DerivedConvertible : Convertible {}
In the sample above, the overload of Convert that does not exist in the abstract parent (and is less derived) is called. I would expect that the most derived version, from the parent class, would be called.
In trying to troubleshoot this problem, I ran into an interesting solution:
public abstract class AbstractConverter<U>
where U : AbstractConvertible
{
public abstract AbstractConverter<U> Convert(U convertible);
}
public class DerivedConvertibleConverter : AbstractConverter<DerivedConvertible>
{
public DerivedConvertibleConverter(DerivedConvertible convertible)
{
Convert(convertible);
}
public override DerivedConvertibleConverter Convert(DerivedConvertible convertible)
{
System.Console.WriteLine("Called the most derived method");
return this;
}
public DerivedConvertibleConverter Convert(Convertible convertible)
{
System.Console.WriteLine("Called the least derived method");
return this;
}
}
public abstract class AbstractConvertible {}
public class Convertible : AbstractConvertible {}
public class DerivedConvertible : Convertible {}
When the derived type argument is removed from the base class, the most derived version of Convert is called. I would not expect this difference, since I would not have expected the interface of the abstract version of Convert to have changed. However, I must be wrong. Can anyone explain why this difference occurs? Thank you very much in advance.
In the sample above, the overload of Convert that does not exist in the abstract parent (and is less derived) is called. I would expect that the most derived version, from the parent class, would be called
Many people have this expectation. However, the behaviour you are observing is correct and by design.
The overload resolution algorithm goes like this. First we make a list of all the possible accessible methods you could be calling. Methods which override virtual methods are considered to be methods of the class which declared them, not the class which overrode them. Then we filter out the ones where the arguments cannot be converted to the formal parameter types. Then we filter out all the methods that are on any type less derived than any type that had an applicable method. Then we determine which method is better than another, if there is still more than one method left.
In your case there are two possible applicable methods. The one that takes a DerivedConvertible is considered to be a method of the base class, and is therefore not as good as the one that takes a Convertible.
The principle here is that overriding a virtual method is an implementation detail subject to change, and not a hint to the compiler that the overriding method is to be chosen.
More generally, these features of the overload resolution algorithm are designed to help mitigate various versions of the Brittle Base Class problem.
For more details about these design decisions see my article on the subject:
http://blogs.msdn.com/b/ericlippert/archive/2007/09/04/future-breaking-changes-part-three.aspx
When the derived type argument is removed from the base class, the most derived version of Convert is called. I would not expect this difference, since I would not have expected the interface of the abstract version of Convert to have changed
The question is based on a false premise; the most derived version is not called. The program fragment is erroneous, and therefore does not compile, and therefore neither method is called; the program doesn't run because it does not compile.