检查一个类是否在运行时实现了一个接口
说FrameworkA
消耗了一个FrameworkA.StandardLogger
类用于记录。我想用另一个替换日志库(SuperLogger
类)。检查一个类是否在运行时实现了一个接口
要做到这一点,有接口:FrameworkA
将提供一个FrameworkA.Logger
接口,其他库必须实现。
但是,如果其他库不实现该接口呢? FrameworkA
可能是一个不够流行的框架,使得SuperLogger
关心其界面。
可能的解决方案是:
- 有一个标准化的接口(由JSR一样,PSR标准定义,...)
- 写适配器
如果什么也没有标准化的接口,你想避免编写无用的适配器的痛苦,如果类是兼容的?
难道没有另一种解决方案来确保类满足合同,但在运行时?
想象(伪代码非常简单的实现):
namespace FrameworkA;
interface Logger {
void log(message);
}
namespace SuperLoggingLibrary;
class SupperLogger {
void log(message) {
// ...
}
}
SupperLogger
与Logger
兼容,只要它实现的记录器接口。但是,而不必FrameworkA.Logger
“硬的依赖”,其公开的“接口”(或签字),可以在运行时验证:
// Something verify that SupperLogger implements Logger at run-time
Logger logger = new SupperLogger();
// setLogger() expect Logger, all works
myFrameworkAConfiguration.setLogger(logger);
在假的情况下,我预计Logger logger = new SupperLogger()
在运行时失败如果该类与接口不兼容,但如果它是成功的话。
这是在OOP中的一个有效的东西吗?如果是,它是否以任何语言存在?如果不是,为什么它是无效的?
我的问题代表静态类型语言(Java,...)或动态类型语言(PHP,...)。对于PHP & al:我知道什么时候没有类型检查你可以使用任何你想要的对象,即使它没有实现接口,但我会感兴趣的东西,实际上检查对象符合与界面。
这就是所谓的鸭打字,您将在红宝石(“它走起来像鸭子,那么它叫起来像鸭子,那么它一定是鸭子”)
在其他动态语言找到一个概念你可以模拟它,例如使用method_exists
。在静态类型语言中可能会有反射的解决方法,搜索“鸭子打字+语言”将有助于找到它们。
啊谢谢你创造这个词!不过,我正在谈论更严格的“鸭子打字”:如果对象与界面不兼容,则失败。而问题是动态类型化语言不会让你定义“接口”,或者如果他们这样做,那么变得静态类型,你不能做鸭子打字(例如PHP有时可以静态类型)。所以最后,静态类型将不允许它,动态类型将允许*任何*。我想允许*任何与界面X兼容的东西* – 2013-02-20 12:56:24
与OOP相比,这更像是一个静态类型的问题。Java和Ruby都是面向对象的语言,但Java可以允许你想要的东西(就像它的静态类型),但是Ruby会(如同它的动态类型一样)。
从静态类型语言的角度来看,主要的(如果不是主要的)优势之一是在编译时知道赋值是否安全有效。你正在寻找的是动态类型语言(比如Ruby)提供的,但不是静态类型语言中可能的 - 这是设计(编译时安全)。
你可以,但它是丑陋的,这样做(在Java中):
Object objLogger = new SupperLogger();
Logger logger = (Logger)objLogger;
这将通过在编译时间,但如果转让无效会在运行时失败。这就是说,以上是相当丑陋,我不会做的事情 - 它不会给你太多,并在运行时冒着不愉快(并可能是令人惊讶)的异常。
我想你可以希望在Java等语言将是抽象的创作远离那些你想使用它的最好:
Logger logger = getLogger();
随着getLogger
决定要返回内部。然而,这只是将实际创作推迟至更低 - 您仍然必须以静态类型的安全方式进行。
只需添加.Net即使静态键入一些聪明的反射也可以让你做到这一点 - 但是你很大程度上放弃了静态类型而没有获得好处的好处那些动态输入 – Basic 2013-02-20 12:14:37
有趣 - 我必须看看那个:-) – 2013-02-20 12:24:21
我也在寻找这种类型系统的语言,但我想你的意思是编译时,而不是运行时,因为对于运行时你几乎可以为任何语言编写代码来检查方法'可用性和签名,并且如果它们不匹配会引发异常。 – user 2016-02-28 18:55:51