I have often wanted the same feature which is asked for e.g. here and in many other questions on SO:
Being able to specify that something satisfies multiple interfaces without specifying the concrete type.
e.g. in C# pseudo syntax
(IEnumerable<string>, INotifyCollectionChanged) GetStringData() {
return /* an object which implements both interfaces */;
}
It is possible to emulate this for method parameters using generics, but not for return values, fields, properties, etc.
Is there a name for this in type theory which I could use to find more information about this?
Are there any (strongishly typed) languages which implement this?
One example where this could be usefull would be an imaginary implementation of Stream.
Currently there is an abstract class with many methods / properties and feature-check properties which enable/disable functionality.
With this feature you could have many interfaces IReadStream
, IWriteStream
, ISeekable
, IHasFixedLength
, etc. and then say Ok, I need something where I can read and seek, so I take (IReadStream + ISeekable)
.
=============== (Too long for a comment)
I think the best way to implement this in C# would be a combination of returning object / explicit casting and checkers implemented with Roslyn which verify that you only cast to 'allowed' interfaces. e.g.
[MultiReturn(typeof(IReaderStream), typeof(ISeekable))]
object GetSeekableReaderStream() {
var stream = new ConcreteReaderWriterSeekableStream();
// stream actually implements IReaderStream, ISeekable AND IWriterStream
// but I only want to expose the first two
return stream;
}
This could then be used like
var stream = GetSeekableReaderStream();
(stream as ISeekable).Seek(5); // OK
(stream as IReaderStream).Read(...); // OK
(stream as IWriterStream).Write(...); // legal for the compiler AND at runtime, but the custom analyzer would scream
Something similar (but different) which is discussed here in roslyn would be "structural interfaces", but they are similar to ducktyping, they only enforce that specific methods are implemented, not that the object implements specific interfaces. Still this would be "near enough" that most of it would be possible.