有人可以给我以下代码拼图的解决方案吗? 给出了一个解决方案,但可能不止一个解决方案。
// this code compiles
IAnimal animal= new Dog();
animal.Eat();
// this code doesn't compile
Dog animal = new Dog();
animal.Eat();
如何将类定义看起来如此,以便上面的代码在不同的作用域中编译(第一个)并且不编译(第二个)?
答案 0 :(得分:4)
您可以使用显式接口实现来实现此目的:
class Dog : IAnimal {
void IAnimal.Eat(){
//do stuff
}
}
与隐式接口实现相反:
class Dog : IAnimal {
public void Eat(){
//do stuff
}
}
答案 1 :(得分:3)
public interface IAnimal
{
void Eat();
}
public class Dog : IAnimal
{
void IAnimal.Eat() { }
}
IAnimal animal = new Dog();
animal.Eat(); // <---- OK
Dog animal2 = new Dog();
animal2.Eat(); // <---- COMPILE ERROR
答案 2 :(得分:3)
第二行的错误是由于类Dog
显式实现IAnimal
接口而导致的错误:
class Dog : IAnimal
{
void IAnimal.Eat()
{
throw new NotImplementedException();
}
}
在这种情况下,您在第二行收到编译错误,因为除非您正在使用Eat
的实例,否则无法致电IAnimal
,因为它本质上是私有的Dog
中的方法。
要修复错误,您需要将实例转发回IAnimal
,就像我上面展示的那样,或者您可以隐式实现这样的界面:
class Dog : IAnimal
{
public void Eat()
{
throw new NotImplementedException();
}
}
答案 3 :(得分:2)
显而易见的解决方案(IAnimal
是接口,Dog
是一个明确实现该接口的类)已在其他答案中提供。
以下是我能想到的其他一些方法。
所有这些都基于IAnimal
这样一个(名字很差的)类
public class IAnimal
{
public void Eat() { }
}
(A)基于定义隐式转换运算符的类的解决方案(请注意,禁止定义从类到接口的转换,这就是为什么将IAnimal
作为类/结构的重要性)
public class Dog
{
public static implicit operator IAnimal(Dog dog) { return new IAnimal(); }
}
在第二个代码段中导致以下编译错误:
错误CS1061:'Dog'不包含'Eat'的定义,并且没有扩展方法'Eat'可以找到接受'Dog'类型的第一个参数(你是否缺少using指令或汇编引用?)
(B)基于基本方法隐藏的解决方案。虽然在C#中我们不能通过在派生类中提供具有不同签名的另一种方法(因为它将被视为重载)来隐藏基本方法,但我们可以通过使用字段来实现,属性或事件,签名不兼容。
例如
public class Dog : IAnimal
{
new public event Action Eat;
}
产生
错误CS0070:事件'Dog.Eat'只能出现在+ =或 - =的左侧(除非在'Dog'类型中使用)
或
public class Dog : IAnimal
{
new public Action<int> Eat;
}
产生
错误CS7036:没有给出对应于'Action'所需的形式参数'obj'的参数