Oop 接口的功能主要是用于使用函数而不知道类是如何构建的吗?
因为我理解接口是契约,所以我将其解释为契约词,即必须具有接口中指定的内容(例如打开、关闭、读取、写入处理文件的接口) 但是我很难理解的是,为什么你需要一个接口来告诉你这个类必须能够做什么,自从你在接口规范中写了它,你就不知道了吗 我能看到的接口的唯一原因是在大型项目中,您希望能够在不真正了解类是如何构建的情况下使用类。通过了解接口需要什么,您将知道如何使用它 这让我想知道为什么我应该在项目中使用(或者如果我应该)接口,而我将是唯一一个从事这项工作的人。我很确定它还有很多我看不到的用途Oop 接口的功能主要是用于使用函数而不知道类是如何构建的吗?,oop,interface,Oop,Interface,因为我理解接口是契约,所以我将其解释为契约词,即必须具有接口中指定的内容(例如打开、关闭、读取、写入处理文件的接口) 但是我很难理解的是,为什么你需要一个接口来告诉你这个类必须能够做什么,自从你在接口规范中写了它,你就不知道了吗 我能看到的接口的唯一原因是在大型项目中,您希望能够在不真正了解类是如何构建的情况下使用类。通过了解接口需要什么,您将知道如何使用它 这让我想知道为什么我应该在项目中使用(或者如果我应该)接口,而我将是唯一一个从事这项工作的人。我很确定它还有很多我看不到的用途 我的大部分
我的大部分假设和解释都来自于和你是对的,接口指定了契约,但实现可能会有很大的不同 简单示例:Java中的列表。列表是一个接口。两种常见的实现是ArrayList和LinkedList。每个人的行为不同,但履行相同的合同。我的意思是,ArrayList具有O(1)(常量)访问权限,而LinkedList具有O(n)访问权限 如果你还不明白O(1)和O(n)是什么意思,我建议你看一下 即使在您自己的代码(即不是或不会成为公共API的代码)上也要这样做的原因是:
- 促进单元测试:你可以模拟一个接口,而你不能(或者不容易)模拟一个类;及
- 允许您稍后更改实现,而不影响调用代码
当您编写外部可用的代码时,它也很好。在这种情况下,代码编写器不是
界面的用户。如果您要向用户提供一个库,那么您可能希望只记录接口
,并允许类
根据上下文进行更改,或者在不更改接口
的情况下随时间发展,假设您正在编写一组实现guns的类。你可能有手枪、步枪和机枪。然后,假设您决定以这样的方式使用这些类,即希望对每一个枪执行fire()操作。你可以这样做:
private Pistol p01;
private Pistol p02;
private Rifle r01;
private MachineGun mg01;
public void fireAll() {
p01.fire();
p02.fire();
r01.fire();
mg01.fire();
}
这种情况很糟糕,因为如果你添加或删除枪,你必须在一些地方更改代码。或者更糟糕的是,假设您希望能够在运行时添加和删除枪:这将变得更加困难
让我们制作一个接口,上面的每种枪都将实现它,称之为火器。现在我们可以这样做了
private Firearm[] firearms;
public void fireAll() {
for (int i = 0; i < firearms.length; ++i) {
firearms[i].fire();
}
}
私人火器[]火器;
公众假期{
对于(int i=0;i<0.length;++i){
火器[i].火();
}
}
这有助于更好地进行更改,不是吗?如果您想重新访问旧代码,您会感谢自己构建了一些接口。没有什么比想要实现一种新的已经存在的东西更令人沮丧的了,结果却发现你不记得一个新的对象必须拥有什么
在Java中,您可以实现多个接口,这在某种程度上模拟了多重继承(具有多个父对象的对象)。您只能扩展一个超类。当您有两个类需要一起工作,但应尽可能彼此解耦时,接口非常有用。一个常见的例子是,在设计模式中使用将模型和视图连接在一起
例如,假设您有一个GUI应用程序,用户可以在其中登录和注销。当用户注销时,您可以更改“当前以某某身份登录”标签,并关闭所有可见的对话框窗口
现在您有了一个User
类和一个logOut
方法,每当调用logOut
时,您都希望所有这些事情都发生。一种方法是让注销
方法处理所有这些任务:
// Bad!
public void logOut() {
userNameLabel.setText("Nobody is logged in");
userProfileWindow.close();
}
这是不赞成的,因为您的用户
类现在与GUI紧密耦合。最好让用户
类更加愚蠢,不要做太多事情。与其关闭userProfileWindow
本身,不如告诉userProfileWindow
用户已经注销,让userProfileWindow
做它想做的任何事情(它想自己关闭)
实现这一点的方法是创建一个通用的UserListener
接口,其中包含一个方法loggedOut
,该方法在用户注销时由User
类调用。任何想知道用户何时登录和注销的人都将实现这个界面
public class User {
// We'll keep a list of people who want to be notified about logouts. We don't know
// who they are, and we don't care. Anybody who wants to be notified will be
// notified.
private static List<UserListener> listeners;
public void addListener(UserListener listener) {
listeners.add(listener);
}
// This will get called by... actually, the User class doesn't know who's calling
// this or why. It might be a MainMenu object because the user selected the Log Out
// option, or an InactivityTimer object that hasn't seen the mouse move in 15
// minutes, who knows?
public void logOut() {
// Do whatever internal bookkeeping needs to be done.
currentUser = null;
// Now that the user is logged out, let everyone know!
for (UserListener listener: listeners) {
listener.loggedOut(this);
}
}
}
// Anybody who cares about logouts will implement this interface and call
// User.addListener.
public interface UserListener {
// This is an abstract method. Each different type of listener will implement this
// method and do whatever it is they need to do when the user logs out.
void loggedOut(User user);
}
// Imagine this is a window that shows the user's name, password, e-mail address, etc.
// When the user logs out this window needs to take action, namely by closing itself so
// this information isn't viewable by other users. To get notified it implements the
// UserListener interface and registers itself with the User class. Now the User.logOut
// method will cause this window to close, even though the User.java source file has no
// mention whatsoever of UserProfileWindow.
public class UserProfileWindow implements UserListener {
public UserProfileWindow() {
// This is a good place to register ourselves as interested observers of logout
// events.
User.addListener(this);
}
// Here we provide our own implementation of the abstract loggedOut method.
public void loggedOut(User user) {
this.close();
}
}
公共类用户{
//我们将保留一份希望收到注销通知的人员列表。我们不知道
//他们是谁,我们不在乎。任何想要得到通知的人都会得到通知
//通知。
私有静态列表侦听器;
公共void addListener(UserListener listener){
添加(侦听器);
}
//这将被调用…实际上,用户类不知道是谁在调用
//这就是原因。它可能是一个主菜单对象,因为用户选择了注销
//选项,或15年内未看到鼠标移动的InactivityTimer对象
//分钟,谁知道呢?
公开作废注销(){
//做任何需要做的内部簿记工作。
currentUser=null;
//现在用户已注销,请让所有人都知道!
for(UserListener侦听器:侦听器){
listener.logge
interface ICrushable
{
void MakeCrushingSound();
}
public class Crusher
{
public void Crush(ICrushable target)
{
target.MakeCrushingSound();
}
}
public class Car : ICrushable
{
public void MakeCrushingSound()
{
Console.WriteLine("Crunch!");
}
}
public class Gorilla : ICrushable
{
public void MakeCrushingSound()
{
Console.WriteLine("Squish!!");
}
}
static void Main(string[] args)
{
ICrushable c = new Car(); // get the ICrushable-ness of a Car
ICrushable g = new Gorilla(); // get the ICrushable-ness of a Gorilla
Crusher.Crush(c);
Crusher.Crush(g);
}
public class Gorilla : ICrushable, IComparable
{
public int Weight
{
get;
set;
}
public void MakeCrushingSound()
{
Console.WriteLine("Squish!!");
}
public int CompareTo(object obj)
{
if (!(obj is Gorilla))
{
throw (new ArgumentException());
}
var lhs = this;
var rhs = obj as Gorilla;
return (lhs.Weight.CompareTo(rhs.Weight));
}
}
var gorillas = new Gorilla[] { new Gorilla() { Weight = 900 },
new Gorilla() { Weight = 800 },
new Gorilla() { Weight = 850 }
};
Array.Sort(gorillas);
var res = Array.BinarySearch(gorillas,
new Gorilla() { Weight = 850 });
template <typename T>
void fun(const T& anObjectOfAnyType)
{
anyThing.anyFunction();
}