接口问题
Trouble with interfaces
我正在处理两个接口:
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'.
无法理解我在这里做错了什么。由于 class Coordinates 确实继承自 ICoordinates。那么这个错误是什么意思?
谢谢
在您的位置 class,您需要使用 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;
}
}
当你有一个接口时,你需要按原样实现它,包括 return 类型。即使 class Coordinates
实现了 ICoordinates
你仍然需要使用精确的签名,你不能改变它。
您已经 解释了您实施 class (Location
) 中 Coordinates1
和 Coordinates2
属性的签名必须与在接口 ILocation
.
中定义的签名
您可能会问为什么会这样。让我们考虑一下,您以外的其他人可能会创建 ICoordinates
接口的替代实现:
class Coordinates : ICoordinates { /* your implementation */ }
class FooCoordinates : ICoordinates { /* an alternative implementation */ }
现在,假设我们有一个 ILocation
对象的引用。根据接口定义,我们可以将 Coordinates1
和 Coordinates2
属性设置为 实现 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;
也就是说,您可以通过首先将 location
转换为它支持的接口类型来将 Coordinates2
设置为 FooCoordinates
对象;然后你会直接通过 location
读回相同的 属性 (没有转换)。根据声明的类型,当 属性 设置为 FooCoordinates
对象时,您会期望得到一个 Coordinates
对象。
或者,换句话说:最后两行代码有问题。倒数第二行代码将 Coordinates
类型的 属性 设置为 FooCoordinates
对象,这当然应该被禁止……但是类型系统无法知道。最后一行代码将从 Coordinates
类型 属性 中读取 FooCoordinates
对象,这同样是不可能的。
只有一种方法可以防止这些丑陋的类型不匹配:您需要完全按照您定义的方式实现接口;包括精确的 return 类型。
我正在处理两个接口:
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'.
无法理解我在这里做错了什么。由于 class Coordinates 确实继承自 ICoordinates。那么这个错误是什么意思?
谢谢
在您的位置 class,您需要使用 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;
}
}
当你有一个接口时,你需要按原样实现它,包括 return 类型。即使 class Coordinates
实现了 ICoordinates
你仍然需要使用精确的签名,你不能改变它。
您已经 Location
) 中 Coordinates1
和 Coordinates2
属性的签名必须与在接口 ILocation
.
您可能会问为什么会这样。让我们考虑一下,您以外的其他人可能会创建 ICoordinates
接口的替代实现:
class Coordinates : ICoordinates { /* your implementation */ }
class FooCoordinates : ICoordinates { /* an alternative implementation */ }
现在,假设我们有一个 ILocation
对象的引用。根据接口定义,我们可以将 Coordinates1
和 Coordinates2
属性设置为 实现 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;
也就是说,您可以通过首先将 location
转换为它支持的接口类型来将 Coordinates2
设置为 FooCoordinates
对象;然后你会直接通过 location
读回相同的 属性 (没有转换)。根据声明的类型,当 属性 设置为 FooCoordinates
对象时,您会期望得到一个 Coordinates
对象。
或者,换句话说:最后两行代码有问题。倒数第二行代码将 Coordinates
类型的 属性 设置为 FooCoordinates
对象,这当然应该被禁止……但是类型系统无法知道。最后一行代码将从 Coordinates
类型 属性 中读取 FooCoordinates
对象,这同样是不可能的。
只有一种方法可以防止这些丑陋的类型不匹配:您需要完全按照您定义的方式实现接口;包括精确的 return 类型。