2015-09-30 3 views
1

Я хочу, чтобы myObject передал определенный класс и назначил его переменной myTargetObject. У меня есть следующий код Scala, но есть ошибка в гипсе:Scala: отбросить объект и присвоить его переменной

def findResult[T](myObject: T): String = { 

    var myTargetObject= None 

    if (myObject.isInstanceOf[myClass1]) { 
     myTargetObject = myObject.asInstanceOf[myClass1] 

    } else if (myObject.isInstanceOf[myClass2]) { 
     myTargetObject = myObject.asInstanceOf[myClass2] 

    } else (myObject.isInstanceOf[myClass3]) { 
     myTargetObject = myObject.asInstanceOf[myClass3] 
    } 
} 

Что должно быть правильным синтаксисом для этой цели? Большое спасибо!

+2

Кастинг, как правило, плохой практики, и то, как вы это делаете, в отчаянии. 'myTargetObject' является' Option [Any] ', поэтому он не будет компилироваться, однако весь код, вероятно, должен быть переписан. Не могли бы вы описать свою проблему высокого уровня для нас, чтобы найти лучшее решение? – Dici

ответ

4

Проблема заключается в том, когда вы делаете var myTargetObject= None, он выводит тип быть Option[Any]None, таким образом пытаясь передать его как myClassN собирается на провал.

правильный способ сделать это с помощью сопоставления:

def findResult[T](myObject: T): String = { 
    myObject match{ 
    case myTargetObject:MyClass1 => { 
     //Actions for MyClass1 
    } 
    case myTargetObject:MyClass2 => { 
     //Actions for MyClass2 
    } 
    case myTargetObject:MyClass3 => { 
     //Actions for MyClass3 
    } 
    case other => { 
     //Default action 
    } 
    } 
} 

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

+0

'Option [Any]', я считаю. BTW с использованием сопоставления с образцами больше Scala-tic, но это все еще выполняет отливки, что обычно невелика. Я буду ждать подробностей о проблеме OP перед повышением, но ответ уже является улучшением кода в вопросе – Dici

+0

@ Dici Спасибо. Обновлено. – resueman

2

ИМХО самый идиоматических способ сделать это в Scala использует классы типов:

class MyClass1(val s: String) 

class MyClass2(val s: String) 

trait ResultFinder[T] { 
    def findResult(t: T): String 
} 

object ResultFinder { 
    def findResult[T: ResultFinder](t: T): String = implicitly[ResultFinder[T]].findResult(t) 

    implicit object RFMyClass1 extends ResultFinder[MyClass1] { 
    override def findResult(t: MyClass1): String = t.s + " of MyClass1" 
    } 

    implicit object RFMyClass2 extends ResultFinder[MyClass2] { 
    override def findResult(t: MyClass2): String = t.s + " of MyClass2" 
    } 
} 

REPL сессия:

scala> import ResultFinder.findResult 
import ResultFinder.findResult 

scala> val c1 = new MyClass1("hello") 
c1: MyClass1 = [email protected] 

scala> val c2 = new MyClass2("hello") 
c2: MyClass2 = [email protected] 

scala> findResult(c1) 
res0: String = hello of MyClass1 

scala> findResult(c2) 
res1: String = hello of MyClass2 

Это решение полностью типобезопасны. Там нет броска, даже под капотом. Вместо этого метод сопоставления образцов использует литые под капотом. Еще одним преимуществом этого решения является то, что он работает для более сложных типов, таких как List[MyClass1], при условии, что в сфере видимости имеется неявный экземпляр. Совпадение шаблонов не будет работать для List[MyClass1] из-за стирания типа.

P.S .: Я полагаю, вы использовали myTargetObject в темп переменной в, но вы на самом деле не нужно, потому что единственный способ выйти из findResult осмысленно является возвращающая String.

+0

сейчас работает. Спасибо! – Edamame

+0

Добро пожаловать! – lambdista

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