2013-02-20 6 views
2

Скажите, 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, если только он реализован интерфейс 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() сбоя во время выполнения если класс не совместим с интерфейсом, но для успеха, если он есть.


ли это быть действительным вещь в ООП? Если да, то существует ли он на любом языке? Если нет, то почему это недействительно?

Мой вопрос означает статически типизированные языки (Java, ...) или динамически типизированные языки (PHP, ...).

Для PHP & al: Я знаю, что когда нет проверки типа, вы можете использовать любой объект, который вам нужен, даже если он не реализует интерфейс, но меня бы интересовало то, что действительно проверяет, что объект соответствует с интерфейсом.

+0

Я также ищу языки с подобным типом системы, но я полагаю, что вы имеете в виду время компиляции, а не время выполнения, поскольку на время выполнения вы можете почти на любом языке написать код, который будет проверять методы «Доступность и подписи и исключение, если они не совпадают. – user

ответ

1

Это называется утка печатая, понятие, которое вы найдете в Ruby («он ходит, как утка, то крякает как утка, то она должна быть утка»)

В других динамически типизированных языках вы можете имитировать его, например, на PHP с method_exists. В статически типизированных языках могут быть обходные пути с отражением, поиск «утиного набора текста + язык» поможет найти их.

+0

ах благодарю вас за то, что вы ввели термин! Однако я говорю о более строгой «утиной печати»: сбой, если объект несовместим с интерфейсом. И проблема в динамически типизированных языках не позволит вам определить «интерфейс», или если они это сделают, то это становится статически типизированным, и вы не можете делать утиную печать (например, PHP иногда может быть статически типизирован). Поэтому, в конце концов, статически типизированный не позволит этого, и динамически типизированный позволит * anything *. Я хочу разрешить * все, что совместимо с интерфейсом X * –

0

Это более статическая типизированная проблема, чем ООП.И Java, и Ruby - это языки OO, но Java woudlnt позволяет то, что вы хотите (как его статически типизированный), но Ruby (как его динамически типизировал).

С точки зрения статически типизированного языка одним из основных (если не основным) преимуществом является знание во время компиляции, если присвоение является безопасным и действительным. То, что вы ищете, обеспечивается динамически типизированными языками (такими как Ruby), но не возможно на статически типизированном языке - и это по дизайну (безопасность времени компиляции).

Вы можете, но это некрасиво, сделать что-то вроде (в Java):

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

Это будет проходить во время компиляции, но потерпит неудачу во время выполнения, если задание было недействительным.

Это говорит о том, что вышесказанное довольно уродливое и не то, что я бы сделал - он не дает вам многого и рискует неприятным (и, возможно, сюрпризом) исключением во время выполнения.

Я думаю, лучшее, что вы могли бы надеяться в язык, как Java будет абстрагировать создание далеко от того, где вы хотите использовать:

Logger logger = getLogger(); 

С внутренностями getLogger решающими, что вернуть. Это, однако, просто отменяет фактическое создание для дальнейшего снижения - вам все равно придется делать это в статически типизированном безопасном виде.

+0

Просто добавьте, что .Net позволит вам сделать это, несмотря на то, что статически типизировано с некоторым умным отражением, - но вы в значительной степени отказываетесь от преимуществ статического ввода без получения те, которые были динамически напечатаны – Basic

+0

Интересно - мне нужно взглянуть на это :-) –

Смежные вопросы