This is design that became de-facto standard for every enterprise solution.
How would you design this in rust?
language = java
interface Collection {
int size();
// Iterator does only one thing, iterate.
// Question about clean, please do not use Iterator::size like it available in rust.
Iterator iterator();
}
abstract class AbstractCollection implements Collection {
@Override
public int size() {
int size = 0;
var iterator = iterator();
while(iterator.hasNext()) {
size++;
iterator.next();
}
return size;
}
}
class ArrayList extends AbstractCollection {
Object[] array;
@Override
public int size() {
return array.length
}
@Override
Iterator iterator() {
...
}
}
class LinkedList extends AbstractCollection {
Node header;
// Assuming that linked list doesn't implement size, the real on in JDK does.
// But in this example, super::size from AbstractCollection is used.
@Override
Iterator iterator() {
...
}
}
UPD:
Let's define the problem a little bit more formally:
You need to implement library for collection.
- On base level you need a interface, that would define set of operation, for simplicity let's go with two operations.
- Iterator and size
- Than in most generic way you can just iterator is count how many items you have, but it is slow and optimal.
- If you know that you concrete implementation Array, you can just use property of array.
- Let's say you have another implementation, which implements methods like Add and Remove - you can bring counter into here, however if we already know that it is Array than counter obviously is redundant.
UPD:
- Add
LinkedListinto example above.
UPD:
More context on problem:
And some extended code examples:
- Problem statement: https://gist.github.com/amidukr/2959073712320ee4a32e7f2266f0febf
- Solution in java: https://gist.github.com/amidukr/cfa97ea987e88239981ac2f6d22e3538
UPD:
Example of OOP with inheritance in Linux kernel:
static struct ata_port_operations ali_early_port_ops = {
.inherits = &ata_sff_port_ops,
.cable_detect = ata_cable_40wire,
.set_piomode = ali_set_piomode,
.sff_data_xfer = ata_sff_data_xfer32,
};
and
static void ata_finalize_port_ops(struct ata_port_operations *ops)
{
static DEFINE_SPINLOCK(lock);
const struct ata_port_operations *cur;
void **begin = (void **)ops;
void **end = (void **)&ops->inherits;
void **pp;
if (!ops || !ops->inherits)
return;
spin_lock(&lock);
for (cur = ops->inherits; cur; cur = cur->inherits) {
void **inherit = (void **)cur;
for (pp = begin; pp < end; pp++, inherit++)
if (!*pp)
*pp = *inherit;
}
for (pp = begin; pp < end; pp++)
if (IS_ERR(*pp))
*pp = NULL;
ops->inherits = NULL;
spin_unlock(&lock);
}
Exact explanation in comment on reddit.