How to return range constructs?
Mike Parker
aldacron at gmail.com
Fri Feb 28 22:27:11 PST 2014
On Friday, 28 February 2014 at 19:02:24 UTC, Robin wrote:
> Hiho,
>
> ok thanks - I haven't known that interfaces are not a "must
> extend" like in java to serve as a real interface to something.
> This is strange to me in first place but has its pros.
Actually, when using code that works with interface types, they
are just like Java.
// API
interface Foo { ... }
void doSomethingWithAFoo( Foo foo );
// User code
class FooImpl : Foo { ... }
But if this is what the API looks like, it's restricting all Foos
to be classes, since in D structs can't extend an interface.
Sometimes, that's exactly what you want to do, but in other cases
it could make sense to allow structs as well. This allows more
flexibility for the user to choose between heap vs. stack, for
example. In D, this can be accomplished by using compile-time
constructs to determine if a type implements a particular
interface. So you could do away with the Foo interface completely
and have something like this.
// API
// A convenient way to test if a type is a Foo
template isFoo( T ) {
enum isFoo = // use compile-time features to test for expected
methods
}
// One way to use isFoo...
void doSomethingWithAFoo( T )( T foo ) if( isFoo!T ) { ... }
// Or, alternatively...
void doSomethingWithAFoo( T )( T foo ) {
static if( isFoo!T ) {
...
} else {
static assert( false, T.stringof ~ " doesn't implement all
Foo methods!");
}
}
// User code
class FooImplA { ... }
struct FooImplB { ... }
As long as both A & B implement all of the methods expected of a
Foo, the template will match and the code will compile. To cover
as many use-cases as possible, which Phobos probably should, it's
useful to have both an object-based interface (interface Foo) and
the template-based structural interface (isFoo). When an API need
not be that all-encompassing, one or the other approach is enough.
More information about the Digitalmars-d-learn
mailing list