Возможно ли реализовать оба scala.collection.Seq [T] и java.util.Список [T] в одном классе

#java #scala #collections

#java #scala #Коллекции

Вопрос:

Я пишу библиотеку на Scala, которую я хотел бы использовать естественным образом как из Scala, так и из Java. Я подумал, что можно было бы написать класс, который расширяет scala.collection.IndexedSeq[T] и реализует java.util.List[T] . Я смог справиться с конфликтом в iterator методе, создав класс, который реализует scala.collection.Iterator и java.util.Iterator , но я в тупике из-за ошибки

столкновение имен между унаследованными членами:
def contains(x$1: Any): Boolean в списке признаков и
def contains[A1 >: T](elem: A1): Boolean в черте SeqLike
имеют тот же тип после удаления: (x$1: Object)Boolean

Есть ли какой-нибудь способ обойти эту ошибку? Реализации методов будут одинаковыми, так что на самом деле все в порядке, что они стираются до одного и того же типа. Должен ли я просто отказаться от этого дурацкого поручения и использовать неявные преобразования и просто иметь дело с накладными расходами на распределение?

Комментарии:

1. Возможно, вы можете использовать java.util.AbstractList<T> и адаптировать список scala и наоборот.

Ответ №1:

Это может быть возможно, но это большая работа, и могут быть задействованы некоторые грязные операции.

Вы не можете реализовать оба типа в Scala, потому что компилятор Scala безопасен для типов. Однако компилятор Java все еще может иметь дело с исключением параметров общего типа.

Итак, это мое предложение по плану — без гарантии, что он будет работать:

  • Создайте класс Java, который расширяет конкретный тип коллекции Scala, такой как ArrayBuffer и реализует java.util.List .
  • Оставьте все параметры универсального типа.
  • Создайте Scala object , который имеет фабричный метод, который возвращает ArrayBuffer[T] with java.util.List[T] .
  • Фабричный метод создает экземпляр класса, упомянутого на первом шаге, и приводит его к возвращаемому типу.

При попытке этого моя ИДЕЯ IntelliJ стала чрезвычайно медленной — предположительно, из-за огромной иерархии типов типов коллекций Scala. Так что я не смог это проверить.

Обратите внимание, что это может открыть ворота для того, кто знает, какие странные ошибки. Я бы определенно не рекомендовал это!

Кроме того, в Scala вам всегда нужно объявлять тип as ArrayBuffer[T] with java.util.List[T] , для которого вы должны определить псевдоним типа.

Я дам вам скелет здесь.

Сначала скелет класса Java с UnsupportedOperationException s для заполнения:

 import scala.collection.generic.Subtractable;
import scala.collection.mutable.ArrayBuffer;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

class MySeqList extends ArrayBuffer implements List {
public static abstract class SeqListIterator implements Iterator, scala.collection.Iterator {
}

@Override
public Subtractable repr() {
    return (Subtractable)super.repr();
}

public boolean add(Object e) {throw new UnsupportedOperationException();}
public Object get(int i) {throw new UnsupportedOperationException();}
public Object set(int i, Object e) {throw new UnsupportedOperationException();}
public void add(int i, Object e) {throw new UnsupportedOperationException();}
public Object remove(int i) {throw new UnsupportedOperationException();}
public int indexOf(Object o) {throw new UnsupportedOperationException();}
public int lastIndexOf(Object o) {throw new UnsupportedOperationException();}
public void clear() {throw new UnsupportedOperationException();}
public boolean addAll(int i, Collection collection) {throw new UnsupportedOperationException();}
public SeqListIterator iterator() {throw new UnsupportedOperationException();}
public ListIterator listIterator() {throw new UnsupportedOperationException();}
public ListIterator listIterator(int i) {throw new UnsupportedOperationException();}
public List subList(int i, int i1) {throw new UnsupportedOperationException();}
public boolean equals(Object o) {throw new UnsupportedOperationException();}
public int hashCode() {throw new UnsupportedOperationException();}
protected void removeRange(int i, int i1) {throw new UnsupportedOperationException();}
public int size() {throw new UnsupportedOperationException();}
public boolean isEmpty() {throw new UnsupportedOperationException();}
public boolean contains(Object o) {throw new UnsupportedOperationException();}
public Object[] toArray() {throw new UnsupportedOperationException();}
public Object[] toArray(Object[] ts) {throw new UnsupportedOperationException();}
public boolean remove(Object o) {throw new UnsupportedOperationException();}
public boolean containsAll(Collection collection) {throw new UnsupportedOperationException();}
public boolean addAll(Collection collection) {throw new UnsupportedOperationException();}
public boolean removeAll(Collection collection) {throw new UnsupportedOperationException();}
public boolean retainAll(Collection collection) {throw new UnsupportedOperationException();}
public String toString() {throw new UnsupportedOperationException();}
}
  

Теперь идет Scala object :

 import scala.collection.mutable.ArrayBuffer

object SeqList {
  def apply[T]():ArrayBuffer[T] with java.util.List[T] = new MySeqList().asInstanceOf[ArrayBuffer[T] with java.util.List[T]]
}
  

Я хочу еще раз подчеркнуть, что это чрезвычайно вонючий код.
Это не похоже на хорошее решение.
Вы можете столкнуться со всевозможными проблемами при реализации методов. Не уверен, что вы столкнетесь с какими-либо блокировками в этом.

Я просто попробовал это, чтобы исследовать границы совместимости Scala / Java, для удовольствия.