NikhilBanerjee
NikhilBanerjee

Reputation: 73

Trouble with interfaces

I am dealing with two interfaces:

public interface ICoordinates
{
    double Latitude { get; set; }
    double Longitude { get; set; }
}

and

public interface ILocation
{
    ICoordinates Coordinate1 { get; set; }
    ICoordinates Coordinate2 { get; set; }
}

Implementing them so:

class Coordinates : ICoordinates
{
    public double Latitude {get; set;}
    public double Longitude {get; set;}

    public Coordinates(double p1, double p2)
    {
        this.Latitude = p1;
        this.Longitude = p2;
    }
}
class Location : ILocation
{
    public Coordinates Coordinate1 { get; set; }
    public Coordinates Coordinate2 { get; set; }

    public Location(Coordinates c1, Coordinates c2)
    {
        this.Coordinate1 = c1;
        this.Coordinate2 = c2;
    }
}

However this gives me a compiler error.

1>C:\Users\Administrator\Documents\Visual Studio 2012\Projects\Twitter_twitinvi\Twitter_twitinvi\Program.cs(36,11,36,19): error CS0738: 'Twitter_twitinvi.Location' does not implement interface member 'Tweetinvi.Core.Interfaces.Models.ILocation.Coordinate2'. 'Twitter_twitinvi.Location.Coordinate2' cannot implement 'Tweetinvi.Core.Interfaces.Models.ILocation.Coordinate2' because it does not have the matching return type of 'Tweetinvi.Core.Interfaces.Models.ICoordinates'.

Can't understand what I m doing wrong here. As class Coordinates does inherit from ICoordinates. So what does this error mean?

Thanks

Upvotes: 1

Views: 124

Answers (2)

You already got a good answer explaining that the signatures of the Coordinates1 and Coordinates2 properties in your implementing class (Location) must exactly match the signatures as they are defined in the interface ILocation.

You might ask why that is so. Let's consider that someone other than you might create an alternate implementation of the ICoordinates interface:

class Coordinates : ICoordinates { /* your implementation */ }

class FooCoordinates : ICoordinates { /* an alternative implementation */ }

Now, let's say we have a reference to an ILocation object. As per the interface definition, we can set the Coordinates1 and Coordinates2 properties to any object that implements ICoordinates. That is, the following would work:

ILocation location = …;
location.Coordinates1 = new Coordinates();
location.Coordinates2 = new FooCoordinates();

Now let's consider your implementation of ILocation. You want to declare your properties to have the type Coordinates instead of ICoordinates (as the interface mandates). If the resulting properties were a legal implementation for ILocation.Coordinates[1|2], then the following would be possible:

Location location = new Location();
ILocation locationAsSeenThroughTheInterface = location;
locationAsSeenThroughTheInterface.Coordinates2 = new FooCoordinates();
Coordinates coordinates2 = location.Coordinates2;

That is, you could set Coordinates2 to a FooCoordinates object by first casting location to the interface type that it supports; then you would read the same property back directly through location (without a cast). According to the declared types, you'd expect to get back a Coordinates object when the property was set to a FooCoordinates object.

Or, in different words: The last two lines of code are problematic. The penultimate line of code would set a property of type Coordinates to a FooCoordinates object, which should of course be forbidden... but the type system would have no way of knowing. The last line of code would read a FooCoordinates object out of a Coordinates-types property, which should be equally impossible.

There is only one way to prevent these ugly type mismatches: You are required to implement the interface exactly as you've defined it; including the precise return types.

Upvotes: 1

krivtom
krivtom

Reputation: 24916

In your location class you need to use properties of type ICoordinates, not Coordinates:

class Location : ILocation
{
    public ICoordinates Coordinate1 { get; set; }
    public ICoordinates Coordinate2 { get; set; }

    public Location(ICoordinates c1, ICoordinates c2)
    {
        this.Coordinate1 = c1;
        this.Coordinate2 = c2;
    }
}

When you have an interface you need to implement it just as it is, including return types. Even though class Coordinates implements ICoordinates you still need to use exact signature, you cannot change it.

Upvotes: 3

Related Questions