2016-11-08 2 views
0

У меня есть класс с несколькими разными конструкторами, которые различаются по типам параметров, когда все эти параметры распространяются от одного и того же базового класса.Scala - выбрать конструктор по времени выполнения аргументов конструктора

Смотрите здесь упрощенный пример:

abstract case class GeneralDataType() 
case class SpecificDataTypeOne() extends GeneralDataType 
case class SpecificDataTypeTwo() extends GeneralDataType 

case class MyNumber(myDataType: Int) extends { 
    def this(data: SpecificDataTypeOne) = this(1) 
    def this(data: SpecificDataTypeTwo) = this(2) 
} 

def getDataType(typeId: Int): GeneralDataType = typeId match { 
    case 1 => new SpecificDataTypeOne 
    case 2 => new SpecificDataTypeTwo 
} 

val x = getDataType(1) 

// error: Cannot resolve constructor 
val mn = new MyNumber(x) 

Как во время выполнения, чтобы выбрать правильный конструктор для использования, в соответствии с типами параметров?

+0

в затмении я получаю это error: case class SpecificDataTypeOne имеет предка GeneralDataType, но наследование на случай отказа. Чтобы преодолеть это ограничение, используйте экстракторы для соответствия шаблону на нелистовых узлах. –

ответ

1

Как другой предложил, попробуйте использовать объект-компаньон, как завод (я до сих пор ошибка, что я добавил в комментарии, но может быть это зависит от версии Scala?)

object MyNumber { 
    def apply(x:GeneralDataType) : MyNumber = x match { 
     case SpecificDataTypeOne() => new MyNumber(1) 
     case SpecificDataTypeTwo() => new MyNumber(2) 
    } 

    def getDataType(typeId: Int): GeneralDataType = typeId match { 
     case 1 => new SpecificDataTypeOne 
     case 2 => new SpecificDataTypeTwo 
    } 
    val x = getDataType(1) 
    val mn = MyNumber(x) 
} 
case class MyNumber(myDataType: Int) 


abstract case class GeneralDataType() 
    case class SpecificDataTypeOne() extends GeneralDataType 
    case class SpecificDataTypeTwo() extends GeneralDataType 
1

Не совсем уверен, что вы используете кейс. В этом случае объект-компаньон может использоваться.

object MyNumber { 
    def apply(typeId: Int): MyNumber = typeId match { 
    case 1 => new MyNumber(new SpecificDataTypeOne) 
    case 2 => new MyNumber(new SpecificDataTypeTwo) 
    } 
} 

val mn = MyNumber(1) 
+0

Привет, я думаю, вы неправильно поняли вопрос. Я получаю объект любого типа (SpecificDataTypeOne или Two) извне, а затем хочу вызвать соответствующий конструктор на основе его типа. –

0

Если вам просто нужно сделать это за один GeneralDataType (или, может быть несколько) и несколько конструкторов каждый, соответствующий шаблон будет делать то, что вам нужно:

x match { 
    case y1: SpecificDataTypeOne => new MyNumber(y1) 
    case y2: SpecificDataTypeTwo => new MyNumber(y2) 
} 

Вы можете сделать более общий решение с использованием отражения, но оно должно использоваться только в том случае, если вышеуказанное недостаточно.

+0

если я пытаюсь перегрузить конструктор MyNumber, чтобы содержать ваш код, он не работает ... –

+0

Вы имеете в виду что-то вроде 'def this (data: GeneralDataType) = data match ...'? Нет, не будет. Вместо этого используйте метод «apply» в сопутствующем объекте, как в ответе Роки Янга (просто возьмите 'GeneralDataType' в качестве аргумента). –

Смежные вопросы