Oop 为什么可以';我似乎不懂界面吗?
有人能帮我揭开界面的神秘面纱,或者给我举一些好的例子吗?我经常看到界面在这里和那里弹出,但我从来没有真正接触过界面的良好解释或何时使用它们Oop 为什么可以';我似乎不懂界面吗?,oop,interface,Oop,Interface,有人能帮我揭开界面的神秘面纱,或者给我举一些好的例子吗?我经常看到界面在这里和那里弹出,但我从来没有真正接触过界面的良好解释或何时使用它们 我是在接口与抽象类的上下文中谈论接口。接口是一种强制对象实现一定数量功能的方法,而不必使用继承(这会导致代码的强耦合,而不是通过使用接口实现的松散耦合) 接口描述的是功能,而不是实现。最简单的答案是接口定义了类的功能。这是一份“合同”,上面说你的类将能够做这个动作 Public Interface IRollOver Sub RollOver() E
我是在接口与抽象类的上下文中谈论接口。接口是一种强制对象实现一定数量功能的方法,而不必使用继承(这会导致代码的强耦合,而不是通过使用接口实现的松散耦合)
接口描述的是功能,而不是实现。最简单的答案是接口定义了类的功能。这是一份“合同”,上面说你的类将能够做这个动作
Public Interface IRollOver
Sub RollOver()
End Interface
Public Class Dog Implements IRollOver
Public Sub RollOver() Implements IRollOver.RollOver
Console.WriteLine("Rolling Over!")
End Sub
End Class
Public Sub Main()
Dim d as New Dog()
Dim ro as IRollOver = TryCast(d, IRollOver)
If ro isNot Nothing Then
ro.RollOver()
End If
End Sub
基本上,您可以保证Dog类只要继续实现该接口,就始终具有滚动的能力。如果猫获得了RollOver()的能力,它们也可以实现该接口,并且当要求猫狗滚动()时,您可以对猫狗进行统一处理。接口允许您根据“描述”而不是类型进行编程,从而允许您更松散地关联软件的元素 可以这样想:你想与你旁边的多维数据集中的某个人共享数据,所以你拿出你的闪存棒并复制/粘贴。你走到隔壁,那家伙说“那是USB吗?”你说是的——一切就绪。闪存棒的大小和制造商无关——重要的是它是USB 同样地,接口允许您对开发进行一般化。使用另一个类比——假设您想要创建一个应用程序,该应用程序可以虚拟地绘制汽车。您可能有这样的签名:
public void Paint(Car car, System.Drawing.Color color)...
public class Fax : ISorteable
{
//implement the ISorteable stuff here.
}
这将一直有效,直到你的客户说“现在我想给卡车喷漆”,所以你可以这样做:
public void Paint (Vehicle vehicle, System.Drawing.Color color)...
这将拓宽你的应用程序。。。直到你的客户说“现在我想粉刷房子!”你从一开始就可以做的就是创建一个界面:
public interface IPaintable{
void Paint(System.Drawing.Color color);
}
public interface IUpdateTracked
{
DateTime LastUpdated { get; set; }
int UpdatedByUser { get; set; }
}
…并将其传递给您的日常工作:
public void Paint(IPaintable item, System.Drawing.Color color){
item.Paint(color);
}
希望这是有意义的-这是一个非常简单的解释,但希望能够触及其核心。简单地说:接口是一个定义了方法但没有实现的类。相反,抽象类实现了一些方法,但不是全部 当你开朋友的车时,你或多或少知道怎么做。这是因为传统汽车都有一个非常相似的界面:方向盘、踏板等等。将此接口视为汽车制造商和驾驶员之间的合同。作为一名驾驶员(软件术语中界面的用户/客户端),你不需要了解不同汽车的细节就能驾驶它们:例如,你只需要知道转动方向盘就能使汽车转向。作为一个汽车制造商(软件方面接口实现的提供者),你清楚你的新车应该有什么以及它应该如何运行,这样司机就可以使用它们,而无需额外培训。这个契约就是软件设计人员所说的解耦(用户与提供商之间的解耦)--客户端代码是使用接口,而不是接口的特定实现,因此不需要知道实现接口的对象的详细信息。接口在类和调用接口的代码之间建立契约。它们还允许您拥有类似的类,这些类实现相同的接口,但执行不同的操作或事件,而不必知道您实际使用的是哪一个。作为一个例子,这可能更有意义,所以让我在这里尝试一个
public class SomeDTO : IUpdateTracked
{
// IUpdateTracked implementation as well as other methods for SomeDTO
}
void SubmitToWorkflow(object o, User u)
{
IUpdateTracked updateTracked = o as IUpdateTracked;
if (updateTracked != null)
{
updateTracked.LastUpdated = DateTime.UtcNow;
updateTracked.UpdatedByUser = u.UserID;
}
// ...
假设你有两门课,叫做狗、猫和老鼠。这些类中的每一个都是Pet,理论上你可以从另一个名为Pet的类继承它们,但问题是。宠物本身不会做任何事情。你不能去商店买宠物。你可以去买一只狗或猫,但宠物是一个抽象的概念,而不是具体的
所以你知道宠物可以做某些事情。他们可以睡觉,吃东西等等。所以你定义了一个叫做IPet的接口,它看起来像这样(C#语法)
您的每个狗、猫和老鼠类都实现IPet
public class Dog : IPet
所以现在这些类中的每一个都必须有自己的Eat和Sleep实现。耶,你有合同。。。现在重点是什么
接下来,假设您想创建一个名为PetStore的新对象。这不是一个很好的宠物店,所以他们基本上只是卖给你一个随机的宠物(是的,我知道这是一个人为的例子)
问题是你不知道它会是什么类型的宠物。多亏了这个界面,尽管你知道不管它是什么,它都会吃和睡
所以这个答案可能一点帮助都没有,但总的想法是,接口让你做一些简单的事情,比如依赖注入和控制反转,你可以得到一个对象,有一个定义良好的对象可以做的事情列表,而不需要真正知道该对象的具体类型 将接口视为合同。当一个类实现一个接口时,它本质上同意遵守该契约的条款。作为消费者,您只关心您拥有的物品是否能够履行其合同义务。它们的内部工作和细节并不重要。接口允许您以通用方式针对对象进行编码。例如,假设您有一个发送报告的方法。现在假设你有一个新的需求,你需要写一份新的报告。如果你能重用你已经写过的方法,那就太好了,对吗?接口使这变得简单:
interface IReport
{
string RenderReport();
}
class MyNewReport : IReport
{
public string RenderReport()
{
return "Hello World Report!";
}
}
class AnotherReport : IReport
{
public string RenderReport()
{
return "Another Report!";
}
}
//This class can process any report that implements IReport!
class ReportEmailer()
{
public void EmailReport(IReport report)
{
Email(report.RenderReport());
}
}
class MyApp()
{
void Main()
{
//create specific "MyNewReport" report using interface
IReport newReport = new MyNewReport();
//create specific "AnotherReport" report using interface
IReport anotherReport = new AnotherReport();
ReportEmailer reportEmailer = new ReportEmailer();
//emailer expects interface
reportEmailer.EmailReport(newReport);
reportEmailer.EmailReport(anotherReport);
}
}
下面是一个我经常使用的与数据库相关的示例。假设您有一个对象和一个容器对象,如列表。让我们假设,有时您可能希望以特定的顺序存储对象。假设序列与
ArrayList ar = (ArrayList)SomeIList;
public class Fax : ISorteable
{
//implement the ISorteable stuff here.
}
public interface ICommand
{
void Execute();
}
public class PrintSomething : ICommand
{
OutputStream Stream { get; set; }
String Content {get; set;}
void Execute()
{
Stream.Write(content);
}
}
INeedFreshFoodAndWater[] array = new INeedFreshFoodAndWater[];
array.Add(new Dog());
array.Add(new Cat());
foreach(INeedFreshFoodAndWater item in array)
{
item.Feed();
item.Water();
}
public interface IReport
{
void RenderReport(); // This just defines the method prototype
}
public abstract class Reporter
{
protected void DoSomething()
{
// This method is the same for every class that inherits from this class
}
}
public class ReportViolators : Reporter, IReport
{
public void RenderReport()
{
// Some kind of implementation specific to this class
}
}
public class ClientApp
{
var violatorsReport = new ReportViolators();
// The interface method
violatorsReport.RenderReport();
// The abstract class method
violatorsReport.DoSomething();
}
using (DisposableClass myClass = new DisposableClass())
{
// code goes here
}
// First pass - not maintainable
void SubmitToWorkflow(object o, User u)
{
if (o is StreetMap)
{
var map = (StreetMap)o;
map.LastUpdated = DateTime.UtcNow;
map.UpdatedByUser = u.UserID;
}
else if (o is Person)
{
var person = (Person)o;
person.LastUpdated = DateTime.Now; // Whoops .. should be UtcNow
person.UpdatedByUser = u.UserID;
}
// Whoa - very unmaintainable.
// Second pass - brittle
void SubmitToWorkflow(object o, User u)
{
if (o is DTOBase)
{
DTOBase dto = (DTOBase)o;
dto.LastUpdated = DateTime.UtcNow;
dto.UpdatedByUser = u.UserID;
}
// Third pass pass - also brittle
void SubmitToWorkflow(DTOBase dto, User u)
{
dto.LastUpdated = DateTime.UtcNow;
dto.UpdatedByUser = u.UserID;
public interface IUpdateTracked
{
DateTime LastUpdated { get; set; }
int UpdatedByUser { get; set; }
}
public class SomeDTO : IUpdateTracked
{
// IUpdateTracked implementation as well as other methods for SomeDTO
}
void SubmitToWorkflow(object o, User u)
{
IUpdateTracked updateTracked = o as IUpdateTracked;
if (updateTracked != null)
{
updateTracked.LastUpdated = DateTime.UtcNow;
updateTracked.UpdatedByUser = u.UserID;
}
// ...
// Using an interface to bridge properties
public class LegacyDTO : IUpdateTracked
{
public int LegacyUserID { get; set; }
public DateTime LastSaved { get; set; }
public int UpdatedByUser
{
get { return LegacyUserID; }
set { LegacyUserID = value; }
}
public DateTime LastUpdated
{
get { return LastSaved; }
set { LastSaved = value; }
}
}
// Explicit implementation of an interface
public class YetAnotherObject : IUpdatable
{
int IUpdatable.UpdatedByUser
{ ... }
DateTime IUpdatable.LastUpdated
{ ... }
// Decouples the caller and the code as both
// operate only on IList, and are free to swap
// out the concrete collection.
public IList<T> FindDuplicates( IList<T> list )
{
var duplicates = new List<T>()
// TODO - write some code to detect duplicate items
return duplicates;
}
class AnnualRaiseAdjuster
: ISalaryAdjuster
{
AnnualRaiseAdjuster(IPayGradeDetermination payGradeDetermination) { ... }
void AdjustSalary(Staff s)
{
var payGrade = payGradeDetermination.Determine(s);
s.Salary = s.Salary * 1.01 + payGrade.Bonus;
}
}
Bird bird = GetMeAnInstanceOfABird(someCriteriaForSelectingASpecificKindOfBird);
bird.Fly(Direction.South, Speed.CruisingSpeed);