2015-12-15 3 views
0

Так что я немного запутался в функции подтипирования. У меня есть следующее, с которым я возился. Я знаю, что для контравариантности A-> Int является подтипом B-> Int, поэтому я смог присвоить AToInt «testBContra».Функция подтипирования и Scala - confused

Но то, что я думал, что я мог сделать, это передать Объект на «testBContra» ...

testBContra (а)

, который не работает. Неужели я не понимаю, что можно передать? Я подумал, что теперь могу передать объект A и вернуть ему Int.

class S(x: Int) { 
    val sInput = x 
} 

class A(x: Int) extends S(x){ 
    val aInput = x 
} 

class B(x: Int) extends A(x){ 
    val bInput = x 
} 

def AToInt(h: A): Int = h.aInput 

// Checking contravariance 

// val testSContra: S=>Int = AtoInt 
val testAContra: A=>Int = AToInt 
val testBContra: B=>Int = AToInt 

val a = new A(2) 
val b = new B(5) 
val s = new S(10) 

testAContra(b) 
testBContra(b) 

ответ

2

testBContra имеет тип B => Int, но так как A не является подтипом B вы не можете оценить testBContra(a). Контрвариантность типов функций используется при назначении функции A => Int на значение с типом B => Int, как вы в

val testBContra: B => Int = AToInt 

Function1 trait контравариантен в его типе параметра и коварианта в своем типе результата. Контравариантность означает, что если A является супертипом B, тогда функция A => T является подтипом функции B => T для некоторого типа результата T. Контравариантность меняет направление отношения супер/подтипа. Это означает, что если у вас есть функция:

def foo(f: B => Int) 

вы можете назвать это непосредственно AtoInt потому что A => Int является подтипом B => Int т.е.

foo(AToInt) 

без контрвариации параметров функции вы бы обернуть AToInt в функции с аргументом типа B т.е.

foo((b: B) => AToInt(b)) 

ковариация возвращаемых функций означает, что если B является подтипом A, то функция T => B является подтипом T => A для некоторого типа ввода T. В вашем примере, поскольку Int является подтипом AnyVal и Any, AToInt является подтипом A => AnyVal и A => Any. Так что если у вас есть функция

def bar(f: A => AnyVal) = f(new A()) 

, то вы можете позвонить bar(AToInt).

Два вида дисперсии могут быть объединены, так что, например, AToInt также подтип B => AnyVal, поскольку A является супертипом B и Int является подтипом AnyVal.

+0

Также это помогает посмотреть, что может сделать 'testBContra'. Скажем, это был «val testBContra: B => Int = _.bInput'. Тогда, очевидно, система типов не была звуковой, если она позволила вам передать значение 'a' типа' A', потому что 'a' не имеет метода' bInput'. –

+0

Спасибо, ребята. Извините, если я плотно об этом. Может быть, я просто написал плохой пример для работы, но как тогда я могу передать что-то для проверкиBContra, которая была бы A => Int?Функция ожидает объект, поэтому, когда я пытаюсь передать ему функцию, она возвращает ошибку – cpd1

+0

@ cpd1 - Почему вы назначаете функцию 'A => Int' переменной типа B = Int и затем пытаетесь вызвать это с экземпляром 'A'? Не можете ли вы просто назвать это напрямую? Не могли бы вы добавить больше подробностей к своему вопросу, чтобы показать, зачем вам это нужно? – Lee

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