I usually program in C# but am trying to do a bit of C++ and am struggling somewhat trying to implement interfaces in C++.
In C# I'd do something like this:
class Base<T>
{
public void DoSomething(T value)
{
// Do something here
}
}
interface IDoubleDoSomething
{
void DoSomething(double value);
}
class Foo : Base<double>, IDoubleDoSomething
{
}
In C++ I've implemented it like this:
template <class T>
class Base
{
public:
virtual void DoSomething(T value)
{
// Do something here
}
};
class IDoubleDoSomething
{
public:
virtual void DoSomething(double value) = 0;
};
class Foo : public Base<double>, public IDoubleDoSomething
{
};
The problem is that I cannot instantiate Foo because it is abstract (doesn't implement DoSomething). I realise I can implement DoSomething and just call the method on Base but I was hoping there is a better way of doing this. I have other classes which inherit from base with different data types and I have other classes which inherit from IDoubleDoSomething which don't use Base.
Any help appreciated.
Consider the following c++ code
class Foo
{
public:
void DoSomething1(){}
};
template<typename t>
void MethodExpectsDosomething1( t f )
{
f.DoSomething1();
}
template<typename t>
void MethodExpectsDosomething2( t f )
{
f.DoSomething2();
}
int main()
{
Foo f;
MethodExpectsDosomething1<Foo>( f );
MethodExpectsDosomething2<Foo>( f );
return 0;
}
In C++ you can use Foo without it implementing a IDoSomething1 and IDoSomething2. The second method MethodExpectsDosomething2 will simply fail to compile as Foo doesn't have the DoSomething2 method.
In C# such construct is not possible and forces you to have IDoSomething1 and IDoSomething2 interface and specify that as a type constraint.
So maybe you need to look at your code and see if such interfaces are needed at all ?
The thing is, Base::DoSomething and IWhatever::DoSomething are two unrelated functions (even if there weren't any pure virtual functions in this, you wouldn't be able to call DoSomething on a Foo object, anyway). Base needs to inherit from IWhatever for this to work.
That said, ask yourself if you actually need this. Generic programming with templates (and concepts, which are sort of like interfaces — see Boost.ConceptCheck) is usually a better solution in C++ than runtime subtype polymorphism.
You could pass a second template parameter to Base, the interface that it is to implement:
template <typename T, class Interface>
class Base : public Interface { ... };
class Foo : public Base<double, IDoubleDoSomething> { ... };
For extra bonus points you could templatise IDoubleDoSomething (so it's eg IDoSomething<double>), or use a traits class to map the type T to the relevant interface.
In C++, pure virtual functions must always be overridden in a derived class; they can't inherit overrides from other base classes like that. If you need dynamic polymorphism, I don't think there's any sensible alternative to writing a function in Foo that calls the Base function. Note that the Base function doesn't need to be virtual.
Depending on how you're using these classes (in particular whether the real type of each instance of the interface is known at compile time), you may be able to use static polymorphism to inject your particular implementation class into its user as a template parameter; for example:
// No explicit interface specification with static polymorphism
class Foo : public Base<double>
{
// Inherits DoSomething(double)
};
// Template can used with any class that impelements a
// "DoSomething" function that can accept a double.
template <class DoubleDoSomething>
void DoSomethingWithDouble(DoubleDoSomething & interface, double value)
{
interface.DoSomething(value);
}
// This particular specialisation uses a "Foo" object.
Foo foo;
DoSomethingWithDouble(foo, 42);
As others have noted, the two functions in the base classes are unrelated (despite having the same name and argument types), as they have no common base class. If you want them to be related, you need to give them a common base class.
Also, in general, if you want multiple inheritance to work properly, you need to declare your non-private base classes as virtual. Otherwise, if you ever have common base classes (as you often need for this style of code), bad things will happen.
So given that, you can make your example work as follows:
template <class T>
class IDoSomething {
public:
virtual void DoSomething(T value) = 0;
};
template <class T>
class Base : public virtual IDoSomething<T>
{
public:
virtual void DoSomething(T value)
{
// Do something here
}
};
class IDoubleDoSomething : public virtual IDoSomething<double>
{
};
class Foo : public virtual Base<double>, public virtual IDoubleDoSomething
{
};
Provided everything else is in order, this should work.
class Foo : public Base<double>
{
};
In your original code Foo would have 2 void DoSomething(double value) methods (1 being abstract).
That would be an Base part and an IDoubleDoSomething part.
Foo::Base and Foo::IDoubleDoSomething.
You could try it by temporarily giving and implementation to IDoubleDoSomething.DoSomething().
But since Foo already "is a" Base" you have what you need without IDoubleDoSomething.
Related
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 ;-)
So this has me perplexed.
Suppose two interfaces.
public interface a
{
void foo();
}
public interface b
{
void foo();
}
Both of those interfaces have a function foo, I have a class that provides explicit implementation:
public class alpha : a, b
{
// why can't I put an access modifier here?
// How would you be able to hide this from a derived class
void a.foo()
{
Console.WriteLine("a");
}
void b.foo()
{
Console.WriteLine("b");
}
}
And a Class that is derived from alpha
public class beta : alpha
{
}
How do you make foo private or protected since alpha doesn't allow access modifiers on explicit imlementation, what can stop someone from calling:
var be = new beta();
(be as b).foo();
EDIT
How come when I don't explicitly provide implementation I can provide an access modifier?
public class alpha : a, b
{
//why this compile?
public void foo()
{
Console.WriteLine("both");
}
}
Since interface a is public, any class that implements a must make the methods of a publicly accessible, either implicitly (through public methods) or explicitly. Explicit implementations are "sort-of" private since they can only be accessed through the interface.
In short, there is no way to completely "hide" foo - your class implements both a and b so those methods must me made accessible through some means.
This would be true even if you only had one interface - having multiple interfaces with a method name collision just forces you to make the implementations explicit. If you had one interface, foo would either have to be public or explicit.
what can stop someone from calling
Nothing, that's the whole point!
beta is a b and thus you can treat it as a b. If you choose to cast it to b and call the explicit foo implementation you'll get b implementation.
As shown in other answers theses are rules of the language and had to be followed.
Sample showing why explicitly specifying public on interface implementation is required:
class Base
{
protected void Foo() { }
}
public interface IFoo
{
void Foo();
}
Class Base explicitly made choice to not expose method Foo to users of the class (except derived, could be private too).
Now if another class wants to derive from Base and implement IFoo at the same time. If language would allow to just pick implementations irrespective of access modifiers it would mean that Base.Foo is now exposed by derived to every caller:
class Derived : Base, IFoo
{
// hypothetical compiler allows to pick any matching `void Foo`
// including inherited `protected void Base.Foo()`
}
This would be clearly against intent of Base class to hide Foo method - so language have to require Foo to be public to be considered as part of interface.
As result you end up with "optional" access modifier on interface implementation where you have exactly one option - must specify public.
Note that Derived has couple options to deal with Foo - explicit implementation and shadowing with new:
class Derived : Base, IFoo
{
new public void Foo() {}
}
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.
Interface methods in C# can be implemented explicitly, so that their implementation is invoked when an instance is explicitly cast to the interface type. Why is this not also supported on virtual methods of classes?
Although working around the 'multiple inheritance' issue is unique to interfaces, it seems that for every other reason that explicitly implemented members would be useful for interfaces, they would also be useful for virtual methods. A cleaner return-type covariance model springs to mind.
Edit: By request, an example:
public class Foo {
...
}
public class Bar : Foo {
...
}
class Base {
abstract Foo A ();
}
class Dervied {
private Bar _b;
Bar A () {
return _b;
}
Foo Base.A () {
return _b;
}
}
I am aware of using helper methods to simulate this, but the net effect seems to have any of the bad characteristics that explicit implementation would have, but with a dirtier API. The crux of my question is not how to do return type covariance, but why a similar mechanism for interfaces is not supported for virtual methods.
Some people recommend not having public virtual methods in the first place. But instead create one public non virtual method representing the consumer interface, and one protected virtual method representing the implementer interface.
I would not call separating the contracts for caller and implementer "muddying the design". In many cases it's cleaner IMO, but I'm usually too lazy to actually do it that way.
This design works much better with return type covariance and method hiding.
An additional benefit of this is that the public wrapper can add additional checking code and supports different contracts for the caller and implementer.
An example of how I'd emulate return type covariance:
public class Base
{
protected virtual Base FooOverride(int i){return new Base();};//FooOverride does not need to duplicate the argument checking
public Base Foo(int i)
{
if(i<0)
throw new ArgumentException("i<0");
return FooOverride(i);
}
}
public class Derived:Base
{
protected override Base FooOverride(int i){return new Derived();};
public new Derived Foo(int i)
{
return (Derived)base.Foo();
}
}
What benefit would that have, besides from allowing something like this?
class Base
{
virtual void M() { }
}
class Derived : Base
{
override void M() { }
override void Base.M() { }
}
This effectively bakes a violation of the Liskov Substitution Principle into the C# language - if I have a variable of type Base, calling M() on it can do entirely different things depending on whether the run-time type is Base or Derived.
Explicit interface implementation is different. Say you have this:
interface IFoo
{
void DoStuff();
}
interface IBar
{
void DoStuff();
}
class C : IFoo, IBar
{
void IFoo.DoStuff() { }
void IBar.DoStuff() { }
}
This preserves the LSP - if I have an IFoo variable that happens to be of run-time type C, calling DoStuff() on it will get the IFoo implementation of it. Likewise with IBar.
I have the following interface:
internal interface IRelativeTo<T> where T : IObject
{
T getRelativeTo();
void setRelativeTo(T relativeTo);
}
and a bunch of classes that (should) implement it, such as:
public class AdminRateShift : IObject, IRelativeTo<AdminRateShift>
{
AdminRateShift getRelativeTo();
void setRelativeTo(AdminRateShift shift);
}
I realise that these three are not the same:
IRelativeTo<>
IRelativeTo<AdminRateShift>
IRelativeTo<IObject>
but nonetheless, I need a way to work with all the different classes like AdminRateShift (and FXRateShift, DetRateShift) that should all implement IRelativeTo. Let's say I have a function which returns AdminRateShift as an Object:
IRelativeTo<IObject> = getObjectThatImplementsRelativeTo(); // returns Object
By programming against the interface, I can do what I need to, but I can't actually cast the Object to IRelativeTo so I can use it.
It's a trivial example, but I hope it will clarify what I am trying to do.
If I understand the question, then the most common approach would be to declare a non-generic base-interface, i.e.
internal interface IRelativeTo
{
object getRelativeTo(); // or maybe something else non-generic
void setRelativeTo(object relativeTo);
}
internal interface IRelativeTo<T> : IRelativeTo
where T : IObject
{
new T getRelativeTo();
new void setRelativeTo(T relativeTo);
}
Another option is for you to code largely in generics... i.e. you have methods like
void DoSomething<T>() where T : IObject
{
IRelativeTo<IObject> foo = // etc
}
If the IRelativeTo<T> is an argument to DoSomething(), then usually you don't need to specify the generic type argument yourself - the compiler will infer it - i.e.
DoSomething(foo);
rather than
DoSomething<SomeType>(foo);
There are benefits to both approaches.
unfortunately inheritance doesn't work with generics. If your function expects IRelativeTo, you can make the function generic as well:
void MyFunction<T>(IRelativeTo<T> sth) where T : IObject
{}
If I remember correctly, when you use the function above you don't even need to specify the type, the compiler should figure it out based on the argument you supply.
If you want to keep a reference to one of these IRelativeTo objects inside a class or method (and you don't care what T is that), you need to make this class/method generic again.
I agree, it is a bit of pain.
If all you care about is that IRelativeTo deals with IObjects then you don't need to make it generic:
interface IRelativeTo
{
IObject getRelativeTo();
void setRelativeTo(IObject relativeTo)
}
The implementing classes may still be generic, however:
abstract class RelativeTo<T> : IRelativeTo where T : IObject
{
public virtual T getRelativeTo() {return default(T);}
public virtual void setRelativeTo(T relativeTo) {}
IObject IRelativeTo.getRelativeTo() {return this.getRelativeTo(); }
void IRelativeTo.setRelativeTo(IObject relativeTo)
{ this.setRelativeTo((T) relativeTo);
}
}
class AdminRateShift : RelativeTo<AdminRateShift>, IObject {}
Then you can do this:
IRelativeTo irt = new AdminRateShift();
IObject o = irt.getRelativeTo();
irt.setRelativeTo(o);