2013-08-28 3 views
11

У меня есть следующий макрос определения класса и возвращает экземпляр этого класса (с Scala 2.10.2 и макро-плагин):метод не может быть доступна в Macro сгенерированного класса

def test[T] = macro testImpl[T] 

def testImpl[T : c.WeakTypeTag](c: Context): c.Expr[Any] = { 
    import c.universe._ 
    val className = newTypeName("Test") 

    c.Expr { q""" 
    class $className { 
     def method = 1 
    } 
    new $className 
    """} 
} 

Когда я называю макро :

case class Cat(name: String) 

val t = test[Cat].method 

Я получаю следующее сообщение об ошибке:

method method in class Test cannot be accessed in Test 
val t = test[Cat].method 
       ^

Моя общая цель состоит в том, чтобы использовать vampire methods и использовать квази-кавычки для описания сгенерированного класса. Как я могу решить эту ошибку?

+0

Разве ваш синтезированный класс не расшифровывает черту, которая абстрактно определяет метод? –

+0

Нет, потому что мне нужно сгенерировать эти методы с определенными именами. И, пытаясь сделать это, я понял, что даже не могу получить доступ к не созданным методам. Я подозреваю, что здесь я не использую квазициты. – Eric

+0

Я понятия не имел, что теперь есть плагин для компилятора для mac paradise (в отличие от принудительного использования разветвленного компилятора). Если только для того, чтобы узнать это, большое спасибо за ваш вопрос. –

ответ

10

В моем посте по методам вампиров я упоминаю this workaround за this bug. По какой-то причине вы в настоящее время не можете видеть методы анонимного класса в экземпляре, возвращаемом из макроса, если вы не создаете класс-оболочку, который расширяет класс с помощью методов и вместо этого возвращает экземпляр этого.

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

c.Expr { q""" 
    class $className { 
     def method = 1 
    } 
    new $className {} 
    """} 

Обратите внимание, что все, что я сделал, это добавить пару скобок в строки, создающей экземпляр, так что я получаю экземпляр анонимного класса, простирающейся $className, а не просто $className.

Я понятия не имею, что стоит за этой ошибкой, и я не уверен, что Юджин знает больше. Недавно я подтвердил, что он все еще находится в последней версии 2.11.

+1

Я расскажу об этом на следующей встрече с отражением. –

+1

Я знал, что вы войдете в Тревис. Благодаря! Теперь я могу подготовить следующий вопрос :-) – Eric

+1

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