As long as the functionality you'd like to test doesn't invoke any pure virtual methods and isn't overridden in subclasses, I'd stick with your bullet point number 1 - creating a test-specific subclass. You could name it Sub<ClassName>
or any generic name reflecting that the subclass itself is not important.
Now if what you want to test can be altered in any way by the final concrete class, you might want to consider this :
I don't know if there's an equivalent in the C++ test framework you're using, but NUnit (and I believe JUnit) let you implement the Abstract Test pattern.
In short, you have
An abstract base test class. It contains a abstract factory method used to generate the object under test, and the test methods per se. These methods verify things that must stay true regardless of the concrete object underneath.
As many derived test classes as there are derivatives of the abstract class under test. You just have to implement the factory method here to return an instance of the derived class.
When the test runner sees a derived test class, it will automatically execute all test methods inherited from the base test class against the factory method-generated object.
First of all, Iterate
is a lame name for that interface, it should be called Iterator
, so I will be calling it Iterator
in this answer, because I am allergic to bad naming.
You say that you encounter this issue often, and I have to believe you, but I also ought to mention my experience, which is that I have rarely, if ever, encountered this need in the last couple of decades that I have been doing OOP.
Usually, when such a need appears to arise, it is an indication that some other aspect of the design needs refactoring.
The first suspect to examine is the CopyTable()
function: why does it need both an Iterator
and a Streamable
for both the source and the destination table? Why can't it just stream-out the source table to bytes and then stream-in the bytes into the destination table? And why is it even called CopyTable
when it is probably just CopyStreamable()
or CopyStreamableIterator()
at worse?
If there is nothing that can be done about the function, then the best approach in my opinion is to combine the two interfaces into one. The name CopyStreamableIterator()
which describes what the function does immediately tells you that you need a StreamableIterator
interface which combines Streamable
and Iterator
. There is nothing wrong with that, and you do not even have to make your Table
class implement that new interface, you can simply implement a StreamableIteratorDecorator
(see decorator pattern) which accepts a Streamable
and an Iterator
as constructor parameters and implements the StreamableIterator
interface by delegating to them. (Though you will probably just declare your Table
class as implementing this interface to be done real quick, because your Table
already implements these methods, so it is good to go.)
Note: I am presuming that in Delphi, just as in Java and C#, a class may extend only one class but multiple interfaces, and that an interface may also extend multiple interfaces, but even if by any chance this is not true, this functionality can be emulated by aggregating interface implementations into classes and adding to classes and interfaces methods that return sub-interfaces.
Amendment
Thinking about it a bit more, I am realizing that your problem may lie in that ill-named IIterate
interface. This interface is trying to cut corners, so it is built in such a way as to force manipulation of the internal state of the underlying (implementing) object. This causes problems, because it is forcing you to have two separate interfaces, one for altering the internal state of your table to select a row, and another interface for reading/writing the currently selected row.
In a language like C# and Java your table would implement IIterable<IStreamable>
, and IIterable<T>
would have just one method, newIterator() : IIterator<T>
. In turn, IIterator<T>
would be defined as follows:
IIterator<T> = interface //javaesque
function Next : T;
property EOF: boolean;
end;
or as follows:
IIterator<T> = interface //csharpesque
function Current : T;
function HasNext : boolean;
procedure MoveNext;
end;
So, instead of selecting rows, your iteration would be yielding each row which can then be streamed. So, you only need to pass an iterator (or better yet an iterable) to your CopyTable()
function.
Adding rows to the target table can be easily accomplished by implementing a IConsumer<IStreamable>
interface which simply appends the contents of the IStreamable
as a new row at the end of the table.
Best Answer
It's perfectly possible for you to have
and that all compiles perfectly fine. What it is of course not possible to do in Java is to have multiple inheritance, where one class extends two classes (as opposed to implementing two interfaces), so you can't do
and I suspect this is what you're actually trying to do. The solution here is to favour composition over inheritance: