2015-01-06 2 views
2

Например, у меня есть такой код:Как инициализировать параметр типа функции в классе Scala?

class Foo(name: String = "", callback: String => String) { 

    def doCallback(arg: String): String = { 
    callback(arg) 
    } 
} 

Вопросы:

1. В Foo конструктор класса, как дать callback параметра значение по умолчанию? Можно ли установить его на null? Или есть лучшая альтернатива?

class Foo(name: String = "", callback: String => String = null) { 
    ... 
} 

2. Если ответ вопрос нет. 1 не является null, как сделать проверку callback, прежде чем называть его внутри метода doCallback? Например, предположим, что null является приемлемым, я мог бы сделать это следующим образом:

class Foo(name: String = "", callback: String => String = null) { 

    def doCallback(arg: String): String = { 
    if (callback != null) callback(arg) else "" // the checking of not null 
    } 
} 
+1

определить замыкание, которое возвращает нуль задница параметр по умолчанию – markusw

+0

@markusw: спасибо, теперь я понимаю :) – null

+1

Всякий раз, когда это возможно не используйте 'null', используйте' Option' вместо – Andrey

ответ

4
class Foo(name: String = "", callback: Option[String => String] = None) { 

def doCallback(arg: String): String = { 
    val call: Option[String] = callback.map(c => c(arg)) // which will either be None or Some(String) 

    call match { 
     case Some(s: String) => s 
     case None => null 
    } 
    } 
} 

Конечно, если изменить подпись doCallback к Option[String] вам не придется делать по шаблону.

В целом, избегая наличия null s в Скале - хорошая практика. Одно из преимуществ, которое не получает NullPointerException с.

Этот подход, однако, заставляет вас передать ваш callback при создании экземпляра класса в пределах Some().

Или, в соответствии с исходным запросом:

class Foo(name: String = "", callback: String => Option[String] = {(s) => None}) { 

    def doCallback(arg: String): String = { 
    val call: Option[String] = callback(arg) 

    call match { 
     case Some(s: String) => s 
     case None => null 
    } 
    } 
} 
+0

Какая из двух предпочтительных примеров? Второй заставил меня передать обратный вызов, который возвращает 'Option [String]' при создании экземпляра класса 'Foo'. – null

+0

Если я использую ваш второй пример, то я должен использовать код, как это? 'println (new Foo (callback = s => Some (" Hi "+ s)) doCallback (" Scala "))' – null

+0

Да, это выглядит правильно. Какой из них вы предпочитаете полностью, зависит от контекста, в котором вы пишете код. – Andrey

1

Как уже сказал, это хорошо, чтобы обернуть все с Option.
Но если вы просто хотите результат по умолчанию будет "", все может быть немного проще:

val alwaysEmpty = { given: String => "" } 

class Foo(val doCallback: String => String = alwaysEmpty) 
+0

Вы сказали: «Хорошо обернуть все с помощью опции». Мне любопытно, что для свойства другого класса, такого как 'name: String =" "', вы думаете, что лучше обернуть его «Option»?Таким образом: 'name: Option [String] = None' – null

+1

Это зависит от того, что' '' 'означает в каждой ситуации. Если * null * и * empty * описаны как '' '', которые все еще рассматриваются как две разные вещи, тогда их не следует помещать в '' '', а соответственно '' '' и 'Option [String]'. Если * null * и * empty * - одно и то же, то для обоих можно использовать '' ''. –

+1

Я имею в виду ... если вы не собираетесь различать '' '' и 'None', тогда он может оставаться как' String'. Если '' '' имеет два разных значения, тогда он должен быть обернут 'Option', чтобы выразить один из них как« Нет ». –

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