2011-06-10 3 views
1

Я нашел для себя очень интересный факт. Например, я уже писал:Структурный тип

type A = { val st: Set[Any] 
      val start: Set[Any] 
      val Sigma : Set[Char] 
      def tr(f: (Tuple2[Any, Any])=>Boolean): Set[Any] 
      } 
class Fon { 
      val st: Set[Any] 
      val start: Set[Any] 
      val Sigma : Set[Char] 
      def tr(f: (Tuple2[Any, Any])=>Boolean): Set[Any] = Set(out) 
      def out: String = "is just example" 
} 
val a: A = new Fon 
a.tr(f(Tuple2('a',0))) 

Но если я буду стараться зовите a.out - я получаю сообщение об ошибке, что тип А не существует «вне» Что происходит с этим, как это работает ? Спасибо.

+3

Этот код является неправильным. По крайней мере, 'Set [out]' и 'Tuple ['a', 0]' неверны, потому что '[]' используется вместо '()'. Кроме того, это не имеет ничего общего со структурными типами - если вы делаете «val a: AnyRef = new Fon; a.out' он все равно будет жаловаться. –

+0

Возможно, я что-то не понимаю, но могу ли вы сделать следующее: 'type A = {def out: String}; класс AA {def out: String = out2; def out2 = "out2"; val a: A = новый AA; a.out' - result 'String = out2' – dvigal

+0

@lisasha В вашем примере отсутствует'} '. Я предполагаю, что после определения 'out2'. Во всяком случае, это вопрос или заявление? Если вопрос, то да. Если заявление, то я не понимаю, что вы пытаетесь сделать. Вы ожидали, что он потерпит неудачу? Если да, то почему? –

ответ

5

Нет такого метода, как A.out, из-за того, как вы определили тип A. Таким образом, когда вы пытаетесь вызвать метод с именем out на объект типа A, компилятор правильно сообщает вам, что такой метод не существует.

Это не относится к структурной типизации, кстати, если бы вы сделали A чертой и имели Fon, продлите ее, вы столкнетесь с точно такими же проблемами. Более того, это то, как работают статические системы печати - компилятор не может гарантировать, что ваш код является типичным, поэтому он не будет его компилировать.

Если вы хотите вызвать метод out, то вам необходимо обратиться к этому объекту с помощью Fon переменной:

val a: Fon = new Fon 
println(a.out) // works fine, since a is guaranteed to be a Fon and thus have the method 
+0

Весь юмор на самом деле, что мы можем иметь, - это формально определенный тип и класс или singleton, в общем - объект, который будет представлять его для реализации. Может быть и не очень хорошо ... Мне интересно, как и почему компилятор разрешает это - используйте метод 'out' в методе tr и выведите, что класс Fon это тип A. – dvigal

1

В основном это позволяет использовать один объект (Fon), как это было другое (A) при условии, что они имеют одинаковые функции.

С out не является признаком A, который не позволяет вам продолжить.

0

тип A - абстрактный класс или черта. Его переменные-члены и методы являются абстрактными.

type A = {val st: Set[Any] 
    val start: Set[Any] 
    val Sigma: Set[Char] 
    def tr(f: (Tuple2[Any, Any]) => Boolean): Set[Any] 
    } 

Fon - это конкретный класс, просто реализуйте тип A все абстрактные элементы.

class Fon { 
    val st: Set[Any] = null 
    val start: Set[Any] = null 
    val Sigma: Set[Char] = null 

    def tr(f: (Tuple2[Any, Any]) => Boolean): Set[Any] = Set(out) 

    def out: String = "is just example" 
    } 

Таким образом, вы можете определить переменную, тип A, и конкретный экземпляр Fon

val a: A = new Fon 
    println(a.tr(_ => false)) // Set(is just example) 

дополнительно: f: (Tuple2[Any, Any]) => Boolean является абстрактная функция высшего порядка в качестве параметра, так, если вы хотите вызвать метод tr, режим вызова a.tr(f(Tuple2('a',0))) не может разрешить символ f. f: (Tuple2[Any, Any]) => Boolean просто получает параметр и возвращает значение boolean. поэтому (_ => false) - это конкретный инструмент.

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