我正在研究接口,并且已经知道我们无法创建接口的实例。我已经经历了一些已经在stackoverflow上提出的问题,但我更期待一些更基本的东西作为所有这些我的心态说。
因为我已经完成了这个非常正常的示例,我正在隐式地实现一个接口并使用该方法,就好像该方法是类本身一样。
namespace MyConsoleProject
{
class Program : Iinterface
{
public int myfunc(int a, int b)
{
return a * b;
}
static void Main(string[] args)
{
Program obj = new Program();
int result = obj.myfunc(10, 20);
Console.WriteLine(result);
Console.ReadLine();
}
}
interface Iinterface
{
int myfunc(int a, int b);
}
}
我没关系,但看看我调用界面的方式。我创建了一个实例 类和调用接口的功能。首先,我不清楚我正在调用接口方法或类方法。由于班级有相同的方法和身体。那我为什么需要接口呢。
我遇到的最重要的一个是:: 当我需要创建这样的界面实例?
Iinterface objinterface=new Program ();
答案 0 :(得分:2)
假设您有这些类和接口:
public interface IDoesSound {
void Sound();
}
public class Dog : IDoesSound {
public void Sound() {
Console.WriteLine("Dog goes Woof!");
}
}
public class Cat : IDoesSound {
public void Sound() {
Console.WriteLine("Cat goes Mew!");
}
}
这是Main()
:
static void Main(string[] args) {
IDoesSound animal = new Cat(); // animal is an instance of Cat
animal.Sound(); // output: Cat goes Mew!
}
IDoesSound animal
向编译器保证分配给animal
的对象将具有IDoesSound
中声明的所有方法和属性,在本例中仅为void Sound()
。因此,没有什么能阻止我们拥有IDoesSound animal = new Dog()
。
此外,在Main()
,每当我致电animal.Sound()
时,我 呼叫IDoesSound.Sound()
,但Cat.Sound()
。所有接口都保证它具有IDoesSound
中的方法和属性。另一种方法是,通过class Dog : IDoesSound
,Dog
承诺履行IDoesSound
指定的合同。
在一个更实际的例子中,假设你想平均一组数字。您将代码放在方法Average()
中。考虑一下 - 最好将这些数字作为参数来获取Average(List<double>)
或Average(ICollection<double>)
?让我们看看两者的合理实现。
public static double Average(List<double> numbers) {
var workingSum = 0.0;
foreach (var num in numbers) {
workingSum += num;
}
return workingSum / numbers.Count;
}
public static double Average(IEnumerable<double> numbers) {
int count = 0;
var workingSum = 0.0;
foreach (var num in numbers) {
count++;
workingSum += num;
}
return workingSum / count;
}
使用Average(List<double>)
,我无法选择List<double>
或衍生作为参数。我可以从其他集合中收集双打并使用或编写代码来转换它们,但是对于Average(IEnumerable<double>)
,只要参数实现{{{>}, 就不必担心它。 1}}。
因此,接口是LINQ工作的重要组成部分,整个示例可以深入研究(除了.NET Framework之外):
IEnumerable<T>
答案 1 :(得分:1)
请注意,您无法创建界面实例。只有实现它的对象。
如果您创建这样的对象,objinterface
将只有接口公开的属性和方法。除非你施放它,否则你不能使用其余的。
我发现这有用的方法有两种:
1)您使用界面来定义您希望对象实现的合同
2)您想限制对象的外部使用,因此将其用作此类参数。这也允许传入实现接口的任何对象:
public void MyMethod(Iinterface obj)
或者像这样传递一个obj
public Iinterface MyMethod()
通过这种方式,您可以限制使用您传出的内容(稍微)。
答案 2 :(得分:1)
我举一个真实的词来解释界面的意思:界面就像我们的现实形象,但每个人都有自己的现实形象,所有的图像都是真实的! 这个现实有很多方面,但每个人都意识到这些方面的一些方面。
答案 3 :(得分:1)
- &GT;首先,我不清楚我正在调用接口方法或类方法。
您正在调用类方法。你不能调用接口方法。实际上,接口没有方法,只是它的原型(即仅限定义)。
确切地说,你没有打过电话。您正在调用Program类的obj
实例的方法。要像Program.myfunc(10, 20)
一样直接调用类的方法,您需要使方法保持静态。
- &GT;那我为什么需要接口呢。
这里的代码非常简单,因此您无法看到界面的好处。类很少像你那样匹配它们的接口。类通常具有比接口更多的功能。因此,界面类型定义了类必须具有的最小功能(即实现)。
要使用简单的措辞(尽管不完全正确),您可以使用界面在多个类/对象之间定义通用(即共享)功能。这使得处理这些对象变得更加容易,而无需知道您正在处理哪个对象。
例如,le说你正在用几种武器创造一个游戏。您可以创建包含IWeapon
和Speed
成员以及Strength
方法的Vibrate
界面。您的每个武器类都将拥有更多的成员和方法,但它们都必须包含Speed
和Strength
成员以及Vibrate
方法。因此,如果您有一些代码处理某些角色所拥有的武器(即武器类的实例),并且您只需要访问这些武器的常用功能(由界面定义),那么您就不需要需要知道你正在处理什么类型的武器。假设这个角色进入了一个带有重气的房间,它将所有武器的速度和力量降低了10%并使它们振动了一点,你可以对这样的代码进行调整:
foreach(IWeapon w in myCharacter.Weapons) {
w.Speed = w.Speed * 0.9;
w.Strength = w.Strength * 0.9;
w.Vibrate();
}
- &GT;当我需要创建这样的界面实例?
- &GT; Iinterface objinterface = new Program();
当您只需要访问接口定义的公共功能并且不需要访问类定义的对象的额外功能时,这种代码非常有用。当您构建对实现该接口的类的所有对象进行操作的泛型函数时,这尤其有用。例如,假设你想把上面的代码放在一个作为燃气室方法的函数中:
public class GasRoom {
public void ApplyGasEffect(IList<IWeapon> weapons) {
foreach(IWeapon w in weapons) {
w.Speed = w.Speed * 0.9;
w.Strength = w.Strength * 0.9;
w.Vibrate();
}
}
}
注意参数类型IList<IWeapon>
。现在你可以将我角色拥有的所有武器列表传递给这个函数,如下所示:
myGasRoom.ApplyGasEffect(myCharacter.Weapons)
让我们说你最初想要给玩家两个武器,然后玩家进入燃气室,现在你的代码就派上用场了:
//Give the player two weapons to start with.
myCharacter.Weapons = new List<IWeapons>();
IWeapon b = new Bazooka();
myCharacter.Weapons.Add(w);
IWeapon r = new Rocket();
myCharacter.Weapons.Add(r);
//Or you can do it all in one line like this:
//myCharacter.Weapons = new List<IWeapons>() { new Bazooka(), new Rocket() };
//////// Here goes some other code for the game //////
//////// until the player enters the gas room ////////
myGasRoom.ApplyGasEffect(myCharacter.Weapons)
答案 4 :(得分:0)
我们不创建接口实例。你仍然在这里创建类的实例。接口仅提供方法和属性的声明。但是,在实现它时,类是负责提供定义。
现在我们什么时候使用接口?阅读松散耦合和后期绑定。这是一个简单的例子来演示我们可以使用接口的情况。
/// <summary>
/// This class should have a method that returns price of pet food. This class should be able to handle different pet animals
/// which as of now, is unknown
/// </summary>
class PetFood
{
public decimal GetFoodPrice(string petType)
{
IPetAnimal petAnimal = null;
if (petType == "Dog")
{
petAnimal = new Dog();
}
else if (petType == "Cat")
{
petAnimal = new Cat();
}
else
{
MessageBox.Show("This animal is not supported yet.");
return 0M;
}
return petAnimal.GetFoodPrice();
}
}
interface IPetAnimal
{
decimal GetFoodPrice();
}
class Dog : IPetAnimal
{
public decimal GetFoodPrice()
{
return 10M;
}
}
class Cat : IPetAnimal
{
public decimal GetFoodPrice()
{
return 5M;
}
}
答案 5 :(得分:0)
您无法创建界面实例。接口是某种合同,迫使您实现其成员(没有实现代码)
答案 6 :(得分:0)
您的代码将在您的类实例上调用myfunc()
方法。通过实现接口,您可以确保在类中定义接口中声明的方法。