接口问题

时间:2015-04-25 10:24:45

标签: c# interface

我正在处理两个接口:

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

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

实施它们:

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;
    }
}

然而,这给了我一个编译器错误。

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'.

无法理解我在这里做错了什么。由于类Coordinate确实继承自ICoordinates。那么这个错误是什么意思呢?

由于

2 个答案:

答案 0 :(得分:3)

在您的位置分类中,您需要使用Grunt serve类型的属性,而不是ICoordinates

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; } } 实现Coordinates,您仍然需要使用精确签名,但您无法更改它。

答案 1 :(得分:1)

您已经a good answer解释了您的实现类(Coordinates1)中Coordinates2Location属性的签名必须与签名中的签名完全匹配界面ILocation

你可能会问为什么会这样。让我们考虑除您以外的其他人可能创建ICoordinates接口的替代实现:

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

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

现在,我们假设我们引用了一个ILocation对象。根据接口定义,我们可以将Coordinates1Coordinates2属性设置为实现ICoordinates的任何对象。也就是说,以下方法可行:

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

现在让我们考虑一下ILocation的实施情况。您希望声明属性的类型为Coordinates而不是ICoordinates(作为接口要求)。如果生成的属性是ILocation.Coordinates[1|2]的合法实现,则可以执行以下操作:

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

也就是说,您可以通过首先将Coordinates2转换为它支持的接口类型来将FooCoordinates设置为location对象;然后你会通过location直接读回同一个属性(没有演员表)。根据声明的类型,当属性设置为Coordinates对象时,您希望返回FooCoordinates对象。

或者,换句话说:最后两行代码是有问题的。倒数第二行代码会将Coordinates类型的属性设置为FooCoordinates对象,这当然应该被禁止......但是类型系统无法知道。最后一行代码将从FooCoordinates - types属性中读取Coordinates对象,这同样是不可能的。

只有一种方法可以防止这些丑陋的类型不匹配:您需要完全按照您的定义实现接口;包括精确的返回类型。