В Scala, как я могу создать подкласс Java-класса с несколькими конструкторами?
Предположим, у меня есть класс Java с несколькими конструкторами:
class Base {
Base(int arg1) {...};
Base(String arg2) {...};
Base(double arg3) {...};
}
Как я могу расширить его в Scala и по-прежнему предоставлять доступ ко всем трем конструкторам Base? В Scala подкласс может вызывать только один из конструкторов своего суперкласса. Как я могу обойти это правило?
Предположим, что класс Java является устаревшим кодом, который я не могу изменить.
4 ответа
Легко забыть, что черта может расширять класс. Если вы используете черту, вы можете отложить решение, какой конструктор вызвать, например:
trait Extended extends Base {
...
}
object Extended {
def apply(arg1: Int) = new Base(arg1) with Extended
def apply(arg2: String) = new Base(arg2) with Extended
def apply(arg3: Double) = new Base(arg3) with Extended
}
Сами черты могут не иметь параметров конструктора, но вы можете обойти это, используя вместо этого абстрактные члены.
РЕДАКТИРОВАТЬ - это из вопроса в списке рассылки scala, который, как я думал, был продублирован здесь. Мой ответ касается предоставления трех разных конструкторов (т.е. репликации дизайна Java), а не расширения класса
Предполагая, что каждый из ваших конструкторов в конечном итоге создает состояние S
объекта, создайте сопутствующий объект с "статическими" методами для создания этого состояния
object Base {
private def stateFrom(d : Double) : S = error("TODO")
private def stateFrom(s : Str) : S = error("TODO")
private def stateFrom(i : Int) : S = error("TODO")
}
Затем создайте приватный конструктор, принимающий состояние и (публичные) перегруженные конструкторы, которые передаются первичному конструктору.
import Base._
class Base private(s : S) { //private constructor takes the state
def this(d : Double) = this(stateFrom(d))
def this(str : String) = this(stateFrom(str))
def this(i : Int) = this(stateFrom(i))
//etc
}
Это глупый ответ, который, вероятно, сработает, но может потребовать слишком много усилий, если в классе Java слишком много конструкторов, но:
Напишите подкласс в Java, который реализует конструктор, который принимает все входные данные, которые будут делать различные другие конструкторы, и вызывает надлежащий конструктор своего суперкласса, основанный на наличии или отсутствии входных данных (посредством использования "нулевого" или какого-либо значения часового), затем создайте подкласс этого Java-класса в Scala и назначьте значения часового в качестве параметров по умолчанию.
Я выбрал бы наиболее общий (в данном случае String) и выполнял бы внутреннее преобразование самостоятельно, если оно соответствует другим критериям.
Хотя я признаю, что это не лучшее решение, и что-то мне кажется неправильным.:-(