22

I have an interface here named IFish. I want to derive it with an abstract class (WalkingFishCommon) which provides an incomplete implementation, so that classes derived from WalkingFishCommon do not have to implement the CanWalk property:

interface IFish
{
    bool Swim();
    bool CanWalk { get; }
}

abstract class WalkingFishCommon : IFish
{
    bool IFish.CanWalk { get { return true; } }

    // (1) Error: must declare a body, because it is not marked
    // abstract, extern, or partial
    // bool IFish.Swim();

    // (2) Error: the modifier 'abstract' is not valid for this item
    // abstract bool IFish.Swim();

    // (3): If no declaration is provided, compiler says 
    // "WalkingFishCommon does not implement member IFish.Swim()"
    // {no declaration}

    // (4) Error: the modifier 'virtual' is not valid for this item
    // virtual bool IFish.Swim();

    // (5) Compiles, but fails to force derived class to implement Swim()
    bool IFish.Swim() { return true; }
}

I've not yet discovered how to make the compiler happy, while still achieving the goal of forcing classes derived from WalkingFishCommon to implement the Swim() method. Particularly baffling is the delta between (1) and (2), where the compiler alternates between complaining that Swim() isn't marked abstract, and in the next breath complains that it can't be marked abstract. Interesting error!

Any help?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Stabledog
  • 3,110
  • 2
  • 32
  • 43
  • 2
    You could throw a NotImplementedException in IFish.Swim, even though it's not really what you're looking for – BlackBear Aug 08 '13 at 14:36
  • 2
    You have to implement all of the interface. You can declare an empty method and just not use it.. – Botonomous Aug 08 '13 at 14:36
  • Ok, well if it's just a limitation of the language semantics, I can live with that. Perhaps I misread the sources which seemed to suggest this was possible... – Stabledog Aug 08 '13 at 14:38
  • 3
    `public abstract bool Swim();` would work, but it seems you want the interface to be explicitly implemented... – Jon Aug 08 '13 at 14:38
  • @Jon: can you clarify? What I want is that the caller invokes IFish.Swim(), the abstract class contains no implementation, and the compiler forces derived classes to implement Swim(). BlackBear's suggestion of throwing an exception is pending as the fallback plan at the moment. If I just declared a new 'Swim()' in the abstract class, wouldn't that make it inaccessible to callers who just have an IFish reference? – Stabledog Aug 08 '13 at 14:43
  • 3
    @Stabledog: You are implementing the interface explicitly (no `public` methods, instead `IFish.` prefix). This means that they cannot be called on an instance of these fish *unless you cast the instance to `IFish` first*. If you don't implement explicitly then you can call the method on any type that implements the interface. See http://stackoverflow.com/questions/143405/c-sharp-interfaces-implicit-implementation-versus-explicit-implementation – Jon Aug 08 '13 at 14:46
  • Interfaces are meant to guarantee that a class has the methods specified in the interface. If it didn't then it would defeat the purpose. If I have a parameter `IFish` I have no idea what concrete fish will be passed in but I do know for SURE that I can call `CanWalk` and `CanSwim` – Despertar Aug 08 '13 at 22:35

4 Answers4

31

Just declare Swim as abstract and don't try to use explicit interface declaration for it (i.e. remove IFish).

abstract class WalkingFishCommon : IFish
{
    public bool CanWalk { get { return true; } }
    public abstract bool Swim();
}
Servy
  • 202,030
  • 26
  • 332
  • 449
  • Nitpick: this is not *quite* the same: now you can do `((WalkingFishCommon)new SomeFish()).Swim()`. – Jon Aug 08 '13 at 14:39
  • 1
    @ThomasLevesque And if he does, I'll revisit it. I think it's probable that he doesn't require explicit interface implementation, and clearly trying to allow it greatly complicates the problem. – Servy Aug 08 '13 at 14:40
  • 2
    As it turns out, I don't have a specific reason to do "explicit" implementation. I just suffered from a misunderstanding -- I thought one was required to specify the interface name in the derived method declarations, or end up with an unrelated method of the same name. So this answer clarifies and solves the problem. Thanks – Stabledog Aug 08 '13 at 14:47
  • @Stabledog: I dislike this answer because it kept the explicit implementation on the property while switching to public implementation for the method (for obvious reasons). While this is legal, it's highly unusual and in this case confusing. Don't do the same, if you don't need explicit go all public. – Jon Aug 08 '13 at 14:49
  • I think I never saw the unedited version... so no foul! Thanks all, the discussion has been very helpful. – Stabledog Aug 08 '13 at 15:03
  • One more follow-up: is there any value to explicitly declaring IControl.CanWalk in WalkingFishCommon? Should I just take that out -- remove the 'IControl.' -- even though it works in the current context to achieve the goal? – Stabledog Aug 08 '13 at 15:17
  • @Stabledog There really isn't enough context about your problem to answer that. – Servy Aug 08 '13 at 15:21
  • Well I'm trying to understand the tradeoffs between explicit declaration of a method and (I guess it must be called) 'implicit' declarations. As I understand it, the value of an explicit declaration is that you can disambiguate method names if you inherit more than one interface containing the same method name. Is that it? Is that why this syntax feature exists, or is there more to it semantically? – Stabledog Aug 08 '13 at 15:29
  • 2
    @Stabledog if an interface method is implemented explicitly, then you can *only* call that method via identifiers of the interface type; if you haven instance of class that implements the interface explicitly you have to typecast it to the interface before you can call those methods. In my experience, people rarely use explicit implementation unless they need to. See: http://msdn.microsoft.com/en-us/library/vstudio/ms173157.aspx – Michael Edenfield Aug 08 '13 at 15:45
  • Ok, so judging by that link -- I can imagine situations in which I want a single method to satisfy the Paint() member of 2 different base interfaces, and other situations where I would want to have 2 different implementations of Paint(), depending on the underlying interface type. So now I think the syntax rule makes sense, which previously seemed arbitrary and odd! – Stabledog Aug 08 '13 at 15:54
  • 1
    @Stabledog It's also useful in that if you have different interfaces all with methods such as `Count` `Length` `Size` you don't have all three members cluttering up intellisense; you can implement one explicitly and the other three implicitly so that you provide the functionality, but don't confuse the users trying to figure out whether `Count` and `Length` are actually the same thing. – Servy Aug 08 '13 at 15:57
  • You may or may not want to declare the non-abstract member (the property in this example) `virtual` (dtb's answer). – Jeppe Stig Nielsen Dec 23 '16 at 18:10
26

Typically, interfaces are implemented implicitly by defining a public member in the class for each member of the interface:

class MyFish : IFish
{
    public bool CanWalk { get { return ...; } }

    public bool Swim() { return ...; }
}

If you do not want to provide an implementation for one of these members, you can simply make it abstract:

abstract class FishBase : IFish
{
    public virtual bool CanWalk { get { return true; } }

    public abstract bool Swim();
}

If you really need to implement the interface explicitly, you can create two members: one abstract member that must be overridden by the derived class, and one member implementing the interface and forwarding the call to the first member:

abstract class FishBase : IFish
{
    public virtual bool CanWalk { get { return true; } }

    protected abstract bool Swim();

    bool IFish.Swim() { return Swim(); }
}
dtb
  • 213,145
  • 36
  • 401
  • 431
9

If you don't really need to implement the interface explicitly, you could simply do this:

abstract class WalkingFishCommon : IFish {
    public abstract bool CanWalk { get; }
    public abstract bool Swim();

}

If the explicit implementation is important, you can solve the problem by introducing protected abstract methods:

abstract class WalkingFishCommon : IFish {
    bool IFish.CanWalk { get { return CanWalkCore; } }
    bool IFish.Swim() { return SwimCore(); }

    protected abstract bool CanWalkCore { get; }
    protected abstract bool SwimCore();

}
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • A `protected` method will not implement an interface implicitly, only a `public` method will. – Jean Hominal Aug 08 '13 at 14:39
  • The top code will not satisfy the IFish interface and not compile – Keith Payne Aug 08 '13 at 14:40
  • @JeanHominal, and how is this a problem? The protected methods are not the implementation of the interface, they don't even have the same name as in the interface... – Thomas Levesque Aug 08 '13 at 14:41
  • 1
    I am talking about your first sample, not the second. – Jean Hominal Aug 08 '13 at 14:41
  • @KeithPayne, JeanHominal, sorry, I had a copy/paste mistake in my first code snippet, it's fixed now. – Thomas Levesque Aug 08 '13 at 14:42
  • This is a bit off-target from my needs, but it's still interesting -- so what you're saying is that the compiler will force derived classes to implmement SwimCore() or CanWalkCore(), achieving the goal and working around the syntax problem...? – Stabledog Aug 08 '13 at 14:50
  • 1
    @Stabledog, yes, exactly. You satisfy the compiler by providing implementations for the interface members, and you still force derived classes to implement the abstract methods. – Thomas Levesque Aug 08 '13 at 14:55
  • Ok. I'll store that one for when I need it... Servy's answer (http://stackoverflow.com/a/18128890/237059) solves the problem of the moment, which originated in my misunderstanding of the semantics for implementing an interface method. – Stabledog Aug 08 '13 at 14:58
1

Not exactly a solution but maybe you could do something like

interface IWalkingFish
{
    bool CanWalk { get; }
}

interface ISwimmingFish
{
    bool Swim();
}

interface IFish : ISwimmingFish, IWalkingFish
{ }

abstract class WalkingFishCommon : IWalkingFish
{
    bool IWalkingFish.CanWalk { get { return true; } }
}

Then you can use the different interfaces for the abstract and concrete classes.

Raidri
  • 17,258
  • 9
  • 62
  • 65