2

SayFrameworkA使用一个FrameworkA.StandardLogger用于记录的类。我想用另一个(SuperLogger类)替换日志库。

为了实现这一点,有接口FrameworkA将提供FrameworkA.Logger其他库必须实现的接口。

但是如果其他库没有实现该接口怎么办?FrameworkA可能不是一个足够流行的框架来SuperLogger关心它的界面。

可能的解决方案是:

  • 具有标准化接口(由 JSR、PSR 等标准定义...)
  • 写适配器

如果没有标准化的接口,并且如果类兼容,您想避免编写无用适配器的痛苦怎么办?

难道不能有另一种解决方案来确保类符合合同,但在运行时?

想象一下(非常简单的伪代码实现):

namespace FrameworkA;
interface Logger {
    void log(message);
}

namespace SuperLoggingLibrary;
class SupperLogger {
    void log(message) {
       // ...
    }
}

SupperLoggerLogger只要它实现了 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:我知道当没有类型检查时你可以使用任何你想要的对象,即使它没有实现接口,但我会对实际检查对象是否符合接口的东西感兴趣。

4

2 回答 2

1

这被称为鸭子类型,你会在 Ruby 中找到一个概念(“它像鸭子一样走路,它像鸭子一样嘎嘎叫,它一定是鸭子”)

在其他动态类型语言中,您可以模拟它,例如在 PHP 中使用method_exists. 在静态类型语言中,可能存在反射解决方法,搜索“duck typing +language”将有助于找到它们。

于 2013-02-20T11:02:16.650 回答
0

这更像是一个静态类型的问题,而不是 OOP 问题。Java 和 Ruby 都是 OO 语言,但 Java 不会允许你想要的(作为它的静态类型),但 Ruby 会(作为它的动态类型)。

从静态类型语言的角度来看,主要(如果不是主要)优势之一是在编译时知道分配是否安全有效。您正在寻找的是由动态类型语言(例如 Ruby)提供的,但在静态类型语言中是不可能的 - 这是设计使然(编译时安全)。

你可以,但它很丑,做类似的事情(在 Java 中):

Object objLogger = new SupperLogger();
Logger logger = (Logger)objLogger;

这将在编译时通过,但如果分配无效,则会在运行时失败。

也就是说,上面的内容非常丑陋,我不会做 - 它不会给你太多,并且在运行时冒着不愉快(并且可能令人惊讶)异常的风险。

我猜想在 Java 之类的语言中,您所希望的最好的方法就是将创建从您想要使用它的地方抽象出来:

Logger logger = getLogger();

内部getLogger决定返回什么。然而,这只是将实际创建推迟到更远的时间 - 您仍然必须以静态类型安全的方式这样做。

于 2013-02-20T11:30:06.067 回答