2016-02-01 3 views
1

Я довольно новичок в Scala, и часть моего проекта закончилась следующим дизайном.Определение типа и переопределение

trait StringService { 
    def length(s: String): Int 
    def vowels(s: String): Int 
} 

Эти методы используются в качестве параметров

def processStrings(operation: String => Int) = {...} 

звонки как processStrings(ss.length) работают отлично. Теперь я хотел бы абстрактные типа этих методов

type StringFuction = String => Int 

Проблема заключается в том, что реализация как

override def length(s: String): Int = { ... } 

больше не действует. Конечно, я могу пойти с

override def length: StringFunction = { (s: String) => ... } 

но это кажется немного выключенным. Каков правильный путь? Пожалуйста, не стесняйтесь предлагать другой дизайн, если это не настоящий подход Scala.

+0

Ваша первоначальная реализация по-прежнему действует. Почему вы думаете иначе? Вы получаете сообщение об ошибке? –

+0

Не уверен, что вы имеете в виду. Реализация как 'override def length (s: String) = s.length' приводит к ошибке« длина метода ничего не отменяет ». 'override def length: StringFunction = _.length' работает, но мне просто не нравится, почему-то я не понимаю. Хотя, если это рекомендуемый подход, я буду жить с ним. –

+0

Без полного кода было непонятно, что это за метод 'length'. Я могу дать лучший ответ с полным кодом. –

ответ

0

Ну, есть разные способы сделать это, в зависимости от цели, для которой вы хотите использовать свой псевдоним типа. Это работает, например:

type StringFunction = String => Int 
trait Foo { def foo(s: String) = ??? } 
class Bar extends Foo { 
    def foo(s: String) = s.length 
} 

def foobar(f: StringFunction)(s) = f(s) 

foobar(new Bar().foo)("bar") 

Это тоже работает:

type StringFunction = String => Int 
trait Foo { def foo: StringFunction = ??? } 
class Bar extends Foo { 
    override def foo = _.length 
} 


def foobar(f: StringFunction)(s) = f(s) 
foobar(new Bar().foo)("bar") 

Строго говоря, это не одни и те же конструкции: в первом случае Foo.foo является метод, который принимает строковый аргумент и возвращает Int. Во втором случае это метод, который не принимает аргументов и возвращает лямбда-функцию, которая принимает аргумент String и возвращает Int.

Эта разница довольно тонкая, хотя. Это имеет значение для некоторых конкретных случаев, но часто их можно игнорировать.

+0

Да, Scala может сделать вывод, что метод 'foo' имеет тип' StringFunction'. Но я бы хотел использовать тип в черте явно. Как я могу это достичь? –

+0

Метод 'foo' на самом деле _not_ типа' StringFunction'. Существует тонкая разница между функцией и методом, который я попытался объяснить в последнем абзаце. Вы можете сделать член типа 'StringFunction', определив его как' def foo: StringFunction = ??? 'или' val foo: StringFunction = ??? ', как показано в моем втором фрагменте кода. Это, вероятно, будет иметь мало пользы для вас, хотя по сравнению с другим подходом. «Не нравится, по какой-то причине я не понимаю» на самом деле не похож на хорошее инженерное обоснование;) – Dima

+0

Спасибо, Дима. Я так понимаю. Просто надеялся на волшебную особенность Scala, которая может преобразовать метод в лямбду за кулисами. –

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