C# 接口—;什么';重点是什么?
我真的找不到接口的原因。据我所知,这是一种解决C#中不存在的不存在的多重继承问题的方法(至少我被告知) 我所看到的是,您预定义了一些成员和函数,然后必须在类中重新定义它们。从而使接口冗余。这感觉就像是句法上的…嗯,对我来说是垃圾(请不要冒犯我的意思,垃圾就是无用的东西) 下面给出的例子取自堆栈溢出上的另一个C#interfaces线程,我只创建一个名为Pizza的基类,而不是接口C# 接口—;什么';重点是什么?,c#,.net,interface,C#,.net,Interface,我真的找不到接口的原因。据我所知,这是一种解决C#中不存在的不存在的多重继承问题的方法(至少我被告知) 我所看到的是,您预定义了一些成员和函数,然后必须在类中重新定义它们。从而使接口冗余。这感觉就像是句法上的…嗯,对我来说是垃圾(请不要冒犯我的意思,垃圾就是无用的东西) 下面给出的例子取自堆栈溢出上的另一个C#interfaces线程,我只创建一个名为Pizza的基类,而不是接口 class Program { static void Main(string[] args) {
class Program {
static void Main(string[] args) {
IMachine machine = new Machine();
machine.Run();
Console.ReadKey();
}
}
class Machine : IMachine {
private void Run() {
Console.WriteLine("Running...");
}
void IMachine.Run() => Run();
}
interface IMachine
{
void Run();
}
简单示例(取自不同的堆栈溢出贡献)
考虑一下你不能在C#中使用多重继承,然后再看看你的问题 关键是接口代表一个契约。任何实现类都必须具有的一组公共方法。从技术上讲,接口只控制语法,即有哪些方法、它们得到哪些参数以及它们返回什么。通常它们也封装了语义,尽管这只是通过文档实现的 然后,您可以拥有一个接口的不同实现,并随意交换它们。在您的示例中,由于每个pizza实例都是
IPizza
,因此无论您在哪里处理未知pizza类型的实例,都可以使用IPizza
。任何类型继承自IPizza
的实例都保证是可排序的,因为它有一个Order()
方法
Python不是静态类型,因此在运行时保留并查找类型。因此,您可以尝试在任何对象上调用Order()
方法。只要对象有这样一个方法,运行时就会很高兴,如果没有,可能只是耸耸肩说“Meh.”。在C#中并非如此。编译器负责进行正确的调用,如果它只是有一些随机的对象
,编译器还不知道运行时的实例是否会有该方法。从编译器的角度来看,它是无效的,因为它无法验证它。(你可以用反射或动态
关键字来做这些事情,但我想这现在有点过分了。)
还请注意,通常意义上的接口不一定必须是C#
接口
,它也可以是抽象类,甚至是普通类(如果所有子类都需要共享一些公共代码,那么这就很方便了–然而,在大多数情况下,接口
就足够了)。接口=契约,用于(见附件).如果没有在Python中使用的as,C#依赖接口来提供抽象。如果类的依赖项都是具体类型,则不能传入任何其他类型-使用接口可以传入实现该接口的任何类型。接口定义了某个类的提供者之间的契约功能性和相应的消费者。它将实现与契约(接口)分离。您应该了解面向对象的体系结构和设计。您可能希望从wikipedia开始:以下是重新解释的示例:
public interface IFood // not Pizza
{
public void Prepare();
}
public class Pizza : IFood
{
public void Prepare() // Not order for explanations sake
{
//Prepare Pizza
}
}
public class Burger : IFood
{
public void Prepare()
{
//Prepare Burger
}
}
class Program {
static void Main(string[] args) {
IMachine machine = new Machine();
machine.Run();
Console.ReadKey();
}
}
class Machine : IMachine {
private void Run() {
Console.WriteLine("Running...");
}
void IMachine.Run() => Run();
}
interface IMachine
{
void Run();
}
接口实际上是实现类必须遵循的契约,它实际上是我所知道的几乎所有设计模式的基础 在您的示例中,创建接口是因为是Pizza的任何内容(这意味着实现Pizza接口)都保证已实现
public void Order();
在您提到的代码之后,您可以有如下内容:
public void orderMyPizza(IPizza myPizza) {
//This will always work, because everyone MUST implement order
myPizza.order();
}
foreach (Control ctrl in Controls)
{
if (ctrl is MyThemableButton)
((MyThemableButton)ctrl).SetTheme(newTheme);
else if (ctrl is MyThemableTextBox)
((MyThemableTextBox)ctrl).SetTheme(newTheme);
else if (ctrl is MyThemableGridView)
((MyThemableGridView)ctrl).SetTheme(newTheme);
else ....
}
ITradesman tradie = Tradesman.Factory(); // in reality i know it's a plumber, but in the real world you won't know who's on the other side of the tradie assignment.
tradie.Work(); // and then tradie will do the work of a plumber, or electrician etc. depending on what type of tradesman he is. The foreman doesn't need to know anything, apart from telling the anonymous tradie to get to Work()!!
通过这种方式,您使用的是多态性,您所关心的只是对象对order()的响应。Pizza示例很糟糕,因为您应该使用一个抽象类来处理排序,而Pizza应该只覆盖Pizza类型,例如 当您有一个共享属性,但您的类从不同的地方继承时,或者当您没有任何可以使用的公共代码时,您可以使用接口。例如,这是可以被释放的东西
IDisposable
,您知道它将被释放,但您不知道当它被释放时会发生什么
接口只是一个协定,它告诉您对象可以做的一些事情,哪些参数和期望的返回类型。在这种情况下,您可以(也可能会)定义一个Pizza基类并从中继承。但是,接口允许您做其他方式无法实现的事情有两个原因:
2的一个含义是,您可以更改正在使用的类,只需要它实现适当的接口。接口的主要目的是,它在您和实现该接口的任何其他类之间订立契约,使您的代码解耦并允许可扩展性。如果我正在工作在绘制形状的API上,我可能希望使用DirectX或图形调用,或OpenGL。因此,我将创建一个接口,该接口将从您的调用中抽象出我的实现
class Program {
static void Main(string[] args) {
IMachine machine = new Machine();
machine.Run();
Console.ReadKey();
}
}
class Machine : IMachine {
private void Run() {
Console.WriteLine("Running...");
}
void IMachine.Run() => Run();
}
interface IMachine
{
void Run();
}
因此您调用一个工厂方法:MyInterface i=MyGraphics.getInstance()
。然后,您有一个合同,这样您就知道在MyInterface
中可以使用哪些函数。这样,您就可以调用i.drawRectangle
或i.drawCube
,并且知道如果您将一个库换成另一个库,那么这些函数是受支持的
如果在XML fi中使用依赖项注入,那么这一点就变得更加重要
public class Pizza()
{
public void Prepare(PizzaType tp)
{
switch (tp)
{
case PizzaType.StuffedCrust:
// prepare stuffed crust ingredients in system
break;
case PizzaType.DeepDish:
// prepare deep dish ingredients in system
break;
//.... etc.
}
}
}
public interface IPizza
{
void Prepare();
}
public class StuffedCrustPizza : IPizza
{
public void Prepare()
{
// Set settings in system for stuffed crust preparations
}
}
public class DeepDishPizza : IPizza
{
public void Prepare()
{
// Set settings in system for deep dish preparations
}
}
public PreparePizzas(IList<IPizza> pizzas)
{
foreach (IPizza pizza in pizzas)
pizza.Prepare();
}
// This is our back-end implementation of a troll
class Troll
{
void Walk(int distance)
{
//Implementation here
}
}
function SpawnCreature()
{
Troll aTroll = new Troll();
aTroll.Walk(1);
}
class Orc
{
void Walk(int distance)
{
//Implementation (orcs are faster than trolls)
}
}
void SpawnCreature(creatureType)
{
switch(creatureType)
{
case Orc:
Orc anOrc = new Orc();
anORc.Walk();
case Troll:
Troll aTroll = new Troll();
aTroll.Walk();
}
}
interface ICreature
{
void Walk(int distance)
}
public class Troll : ICreature
public class Orc : ICreature
//etc
void SpawnCreature(creatureType)
{
ICreature creature;
switch(creatureType)
{
case Orc:
creature = new Orc();
case Troll:
creature = new Troll();
}
creature.Walk();
}
public class CreatureFactory {
public ICreature GetCreature(creatureType)
{
ICreature creature;
switch(creatureType)
{
case Orc:
creature = new Orc();
case Troll:
creature = new Troll();
}
return creature;
}
}
CreatureFactory _factory;
void SpawnCreature(creatureType)
{
ICreature creature = _factory.GetCreature(creatureType);
creature.Walk();
}
interface ICanTurnToStone
{
void TurnToStone();
}
public class Troll: ICreature, ICanTurnToStone
void SpawnCreatureInSunlight(creatureType)
{
ICreature creature = _factory.GetCreature(creatureType);
creature.Walk();
if (creature is ICanTurnToStone)
{
(ICanTurnToStone)creature.TurnToStone();
}
}
public interface ICreatureFactory {
ICreature GetCreature(string creatureType);
}
public class CreatureController : Controller {
private readonly ICreatureFactory _factory;
public CreatureController(ICreatureFactory factory) {
_factory = factory;
}
public HttpResponseMessage TurnToStone(string creatureType) {
ICreature creature = _factory.GetCreature(creatureType);
creature.TurnToStone();
return Request.CreateResponse(HttpStatusCode.OK);
}
}
interface IRectangular
{
Int32 Width();
Int32 Height();
}
static class Utils
{
public static Int32 Area(IRectangular rect)
{
return rect.Width() * rect.Height();
}
}
class SwimmingPool : IRectangular
{
int width;
int height;
public SwimmingPool(int w, int h)
{ width = w; height = h; }
public int Width() { return width; }
public int Height() { return height; }
}
class House : IRectangular
{
int width;
int height;
public House(int w, int h)
{ width = w; height = h; }
public int Width() { return width; }
public int Height() { return height; }
}
var house = new House(2, 3);
var pool = new SwimmingPool(3, 4);
Console.WriteLine(Utils.Area(house));
Console.WriteLine(Utils.Area(pool));
public abstract class Food {
public abstract void Prepare();
}
public class Pizza : Food {
public override void Prepare() { /* Prepare pizza */ }
}
public class Burger : Food {
public override void Prepare() { /* Prepare Burger */ }
}
public abstract class MenuItem {
public string Name { get; set; }
public abstract void BringToTable();
}
// Notice Soda only inherits from MenuItem
public class Soda : MenuItem {
public override void BringToTable() { /* Bring soda to table */ }
}
// All food needs to be cooked (real food) so we add this
// feature to all food menu items
public interface IFood {
void Cook();
}
public class Pizza : MenuItem, IFood {
public override void BringToTable() { /* Bring pizza to table */ }
public void Cook() { /* Cook Pizza */ }
}
public class Burger : MenuItem, IFood {
public override void BringToTable() { /* Bring burger to table */ }
public void Cook() { /* Cook Burger */ }
}
public class Waiter {
public void TakeOrder(IEnumerable<MenuItem> order)
{
// Cook first
// (all except soda because soda is not IFood)
foreach (var food in order.OfType<IFood>())
food.Cook();
// Bring them all to the table
// (everything, including soda, pizza and burger because they're all menu items)
foreach (var menuItem in order)
menuItem.BringToTable();
}
}
If(electrician) then electrician.FixCablesAndElectricity()
if(plumber) then plumber.IncreaseWaterPressureAndFixLeaks()
ITradesman tradie = Tradesman.Factory(); // in reality i know it's a plumber, but in the real world you won't know who's on the other side of the tradie assignment.
tradie.Work(); // and then tradie will do the work of a plumber, or electrician etc. depending on what type of tradesman he is. The foreman doesn't need to know anything, apart from telling the anonymous tradie to get to Work()!!
class Program {
static void Main(string[] args) {
IMachine machine = new Machine();
machine.Run();
Console.ReadKey();
}
}
class Machine : IMachine {
private void Run() {
Console.WriteLine("Running...");
}
void IMachine.Run() => Run();
}
interface IMachine
{
void Run();
}
interface IShapes
{
void DrawShape();
}
class Circle : IShapes
{
public void DrawShape()
{
Console.WriteLine("Implementation to Draw a Circle");
}
}
Class Triangle: IShapes
{
public void DrawShape()
{
Console.WriteLine("Implementation to draw a Triangle");
}
}
static void Main()
{
List <IShapes> shapes = new List<IShapes>();
shapes.Add(new Circle());
shapes.Add(new Triangle());
foreach(var shape in shapes)
{
shape.DrawShape();
}
}
public interface IMachine
{
bool Start();
bool Stop();
}
public class Car : IMachine
{
public bool Start()
{
Console.WriteLine("Car started");
return true;
}
public bool Stop()
{
Console.WriteLine("Car stopped");
return false;
}
}
public class Tank : IMachine
{
public bool Start()
{
Console.WriteLine("Tank started");
return true;
}
public bool Stop()
{
Console.WriteLine("Tank stopped");
return false;
}
}
class Program
{
static void Main(string[] args)
{
var car = new Car();
car.Start();
car.Stop();
var tank = new Tank();
tank.Start();
tank.Stop();
}
}
interface ICRUD{
void InsertData(); // will insert data
void UpdateData(); // will update data
void DeleteData(); // will delete data
}