接口故障



我正在处理两个接口:

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:UsersAdministratorDocumentsVisual Studio 2012ProjectsTwitter_twitinviTwitter_twitinviProgram.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'.

我不明白我在这里做错了什么。由于类Coordinates确实继承自ICordinates。那么这个错误是什么意思呢?

感谢

在位置类中,您需要使用类型为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实现了ICoordinates,您仍然需要使用精确的签名,但不能更改它

您已经得到了一个很好的答案,解释了实现类(Location)中Coordinates1Coordinates2属性的签名必须与接口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读取回相同的属性(没有强制转换)。根据声明的类型,当属性设置为FooCoordinates对象时,您希望返回一个Coordinates对象。

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

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

最新更新