Вывод типа Scala и получение более конкретного из двух параметров типа в качестве результата метода - PullRequest
2 голосов
/ 09 марта 2012

Что я хотел бы сделать, это определить условия для классов, включая наследование. Если два условия и-ed (или--ed), результатом должно быть условие более конкретного класса, то есть условия запроса. Так что, если у меня есть

class Parent
class Sub extends Parent
class SubSub extends Sub

a Condition[Sub] and Condition[Parent] and Condition[SubSub] должно дать Condition[SubSub]. Условия также должны быть контравариантными, поскольку условие над родителем также должно быть условием над подпрограммой. Таким образом, я определил (AnyRef - дополнительное внешнее ограничение):

class Condition[-A<:AnyRef] {
  def and[R<:A, P>:R<:AnyRef](that:Condition[P]):Condition[R]=
    new AndCondition[R](this, that)
}

class AndCondition[-A<:AnyRef](left:Condition[_>:A], right:Condition[_>:A]) 
  extends Condition[A]

Ввод AndCondition вроде бы в порядке, так как это

val a:AndCondition[SubSub] =
  new AndCondition(
    new AndCondition(
      new AndCondition(
        new Condition[Parent], 
        new Condition[Sub]), 
      new Condition[Parent]),
    new Condition[SubSub])

работает. У меня были проблемы с методом и для вызовов инфикса, и я пришел к приведенному выше определению, которое также работает:

val b: Condition[SubSub] = 
   new Condition[Parent] and 
     new Condition[SubSub] and 
     new Condition[Sub]

... вроде, так как он перестает работать при выполнении четвертого условия:

val c: Condition[SubSub]=
  new Condition[Parent] and 
    new Condition[SubSub] and 
    new Condition[Sub] and 
    new Condition[Parent]

приводит к выводу 'Nothing':

error: inferred type arguments
[com.solvedirect.test.SubSub,com.solvedirect.test.SubSub,com.solvedirect.test.Parent]
do not conform to method and's type parameter bounds 
[R <: Nothing,R <: R,P >: R <: AnyRef]

"Уменьшение" и "цепочки" путем связывания воедино первого и второго двух условий (то есть (a и b) и (c и d)) заставляет его снова компилироваться Думаю, я выбрал неправильный маршрут, но не вижу его. Прошу прощения за неопределенный заголовок вопроса или если на него уже был дан ответ, но я не смог его найти, возможно, также из-за отсутствия описательных поисковых терминов.

Спасибо за ваше время.

С уважением,

Месси

1 Ответ

0 голосов
/ 08 мая 2012

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

Если вы не назначите тип возврата явно, параметр может быть выведен. Поскольку инфиксный оператор (если они не заканчиваются на :) в Scala, остается ассоциативным, в этом выражении:

val c:Condition[SubSub] = new Condition[Parent] and new Condition[SubSub] and
  new Condition[Sub] and
  new Condition[Parent]

компилятор действует так:

 ((new Condition[Parent] and new Condition[SubSub]) and
  new Condition[Sub]) and
  new Condition[Parent])

Итак, вы попадаете в следующую ситуацию:

  • Первое и между Condition [Parent] и Condition [SubSub] возвращает тип, который не может быть выведен и который вы не указали, поэтому это UnknownType1
  • Второй и тот же: это и между UnknownType1 и Условием [Sub], возвращая UnknownType2
  • Третий принимает UnknownType2 и Condition [Parent]. Здесь компилятор не может проверить удержание ограничения.

Обратите внимание, что в случае трех операндов и:

 val b: Condition[SubSub] =
new Condition[Parent] and
  new Condition[SubSub] and
  new Condition[Sub]

Компилятор использовал тип b для определения типа промежуточного результата (Parent и SubSub) и мог проверять границы.

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

Чтобы вернуться к первоначальному комментарию, обратите также внимание, что в простом случае, если вы не укажете результат, компилятор также завершится неудачно, и это обычно является признаком плохого дизайна ваших классов

val e = новое условие [Parent] и новое условие [SubSub]

...