Matthieu Napoli
Matthieu Napoli

Reputation: 49553

Check if a class implements an interface at run-time

Say FrameworkA consumes a FrameworkA.StandardLogger class for logging. I want to replace the logging library by another one (the SuperLogger class).

To make that possible, there are interfaces: FrameworkA will provide a FrameworkA.Logger interface that other libraries have to implement.

But what if other libraries don't implement that interface? FrameworkA might be a not popular enough framework to make SuperLogger care about its interface.

Possible solutions are:

What if there is no standardized interface, and you want to avoid the pain of writing useless adapters if classes are compatible?

Couldn't there be another solution to ensure a class meets a contract, but at runtime?

Imagine (very simple implementation in pseudo-code):

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

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

SupperLogger is compatible with Logger if only it implemented Logger interface. But instead of having a "hard-dependency" to FrameworkA.Logger, its public "interface" (or signature) could be verified at runtime:

// Something verify that SupperLogger implements Logger at run-time
Logger logger = new SupperLogger();

// setLogger() expect Logger, all works
myFrameworkAConfiguration.setLogger(logger);

In the fake scenario, I expect the Logger logger = new SupperLogger() to fail at run-time if the class is not compatible with the interface, but to succeed if it is.


Would that be a valid thing in OOP? If yes, does it exist in any language? If no, why is it not valid?

My question stands for statically-typed languages (Java, ...) or dynamically typed languages (PHP, ...).

For PHP & al: I know when there is no type-check you can use any object you want even if it doesn't implement the interface, but I'd be interested in something that actually checks that the object complies with the interface.

Upvotes: 2

Views: 284

Answers (2)

Sean Landsman
Sean Landsman

Reputation: 7179

This is more of a statically typed issue than a OOP one. Both Java and Ruby are OO languages, but Java woudlnt allow what you want (as its statically typed) but Ruby would (as its dynamically typed).

From a statically typed language point of view one of the major (if not the major) advantage is knowing at compile time if an assignment is safe and valid. What you're looking for is provided by dynamically typed languages (such as Ruby), but isnt possible in a statically typed language - and this is by design (compile time safety).

You can, but it is ugly, do something like (in Java):

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

This would pass at compile time but would fail at runtime if the assignment was invalid.

That said, the above is pretty ugly and isnt something I would do - it doesnt give you much and risks an unpleasant (and possibly suprising) exception at runtime.

I guess the best you could hope for in a language like Java would be to abstract the creation away from where you want to use it:

Logger logger = getLogger();

With the internals of getLogger deciding what to return. This however just defers the actual creation to further down - you'll still have to do so in a statically typed safe way.

Upvotes: 0

Fabian Schmengler
Fabian Schmengler

Reputation: 24551

This is called duck typing, a concept that you will find in Ruby ("it walks like a duck, it quacks like a duck, it must be a duck")

In other dynamically typed languages you can simulate it, for example in PHP with method_exists. In statically typed languages there might be workarounds with reflection, a search for "duck typing +language" will help to find them.

Upvotes: 1

Related Questions