Java – how to limit a self referencing type?

I have things (for example, context, number) that I can perform operations on my own type:

interface Number<N> {
    N add(N to);
}
class Int implements Number<Int> {
    Int add(Int to) {...}
}

And actors acting on all subtypes of a ceiling:

interface Actor<U> {
    <E extends U> E act(Iterable<? extends E> items);
}

I want an actor to be polymorphic on any numeric type:

class Sum implements Actor<Number> {
    <N extends Number<N>> N act(Iterable<? extends N> items) {...}
}

Now, obviously, this doesn't work because number is different from number < n >. In fact, such an actor can't work because number doesn't limit the implementer's type parameter to its own type But I don't care about the general operation of numbers - I'm very satisfied that my function can only work on some types of numbers n extension number < n >

Instead, I can state:

interface Actor<E> {
    E act(Iterable<? extends E> items);
}

class Sum<N extends Number<N>> implements Actor<N> {
    N act(Iterable<? extends N> items) {...}
}

But it doesn't work for me, because when I build my sum, I force me to know n, my use case is inconvenient It also forces an ugly < n extended number n > to cause the proliferation of type clutter in each class or method using sum

Is there any elegant way to do what I want?

Example:

Here are some sample code to express what I want to do

interface Folder<U> {
    <E extends U> E fold(Iterable<? extends E> items);
}

class Sum implements Folder<Number> {
    <N extends Number<N>> N fold(Iterable<? extends N> items) {
        Iterator<? extends N> iter = items.iterator();
        N item = iter.next();
        while (iter.hasNext())
            item = item.add(iter.next());
        return item;
    }
}

class Concat implements Folder<String> {
    <S extends String> fold(Iterable<? extends S> items) {
        StringBuilder concatenation = new StringBuilder();
        for (S item : items)
            concatenation.append(item);
        return concatenation.toString();
    }
}

class FoldUtils {
    static <U,E extends U> E foldDeep(Folder<U> folder,Iterable<? extends Iterable<? extends E>> itemses) {
        Collection<E> partialResults = new ArrayList<E>();
        for (Iterable<? extends E> items : itemses)
            partialResults.add(folder.fold(items));
        return folder.fold(partialResults);
    }
}

Solution

Look at your example. I don't know what to get from the actors by providing specific parameters from the general method:

class Sum<T extends Number<T>> implements Actor<T> {
    T act(Iterable<? extends T> items) {...}
}

What are the advantages of having a sum < any self referential number >? Vs only sum < int > and sum < float > and so on

If you're worried about the small memory overhead of creating different instances, you can use unchecked transformations every time you return the same instance, as safe as usual (see, for example, guava's optional. Absent() or collections emptyList()) .

In your example, someone has to basically do:

List<List<Int>> list;
foldDeep(new Sum(),list)

So why not require type parameters?

foldDeep(new Sum<Int>(),list)

Or if it's packaged behind the factory,

foldDeep(Sum.instance(),list)
foldDeep(NumberFolders.sum(),list)

In short, I don't know why this won't work:

interface Folder<U> {
    U fold(Iterable<? extends U> items);
}

class Sum<T extends Number<T>> implements Folder<T> {
    public T fold(Iterable<? extends T> items) {
        //...
    }
}

class FoldUtils {
    static <E> E foldDeep(Folder<E> folder,Iterable<? extends Iterable<? extends E>> itemses) {
        Collection<E> partialResults = new ArrayList<>();
        for (Iterable<? extends E> items : itemses)
            partialResults.add(folder.fold(items));
        return folder.fold(partialResults);
    }
}

//...
FoldUtils.foldDeep(new Sum<>(),list);
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>