научился двум вещам в скале
Dec. 16th, 2012 09:12 am1. magnet pattern
Вместо того, чтобы определять с полдюжины методов, берущих разные комбинации типов параметров, взять какой-то один тип, скажем, даже специально придуманный, и написать некоторое количество имплиситов, которые бы приводили ваши типы к этому специально придуманному. API становится прозрачным как слеза комсомолки; а все эти приводы (приведения) выписаны отдельно, например:
2. Composing inheritance
У меня там был определён метод log(msg: String) = println(msg); но это как-то слишком примитивно, хорошо для repl, но не для сервлета, ну и т.д. Josh Suereth учит - а вы выдерните всю эту хрень в трейты:
И пишите типа
А в конкретных классах можно писать
Цимес в том, что
Вместо того, чтобы определять с полдюжины методов, берущих разные комбинации типов параметров, взять какой-то один тип, скажем, даже специально придуманный, и написать некоторое количество имплиситов, которые бы приводили ваши типы к этому специально придуманному. API становится прозрачным как слеза комсомолки; а все эти приводы (приведения) выписаны отдельно, например:
/** * All obvious stuff goes here * Uses "magnet pattern" (lmgtfy) */ object Obvious { implicit def asSource(in: InputStream): Source = Source.fromInputStream(in) implicit def asSource(in: HttpServletRequest): Source = asSource(in.getInputStream) implicit def asWriter(out: OutputStream): Writer = new OutputStreamWriter(out) implicit def asWriter(out: HttpServletResponse): Writer = asWriter(out.getOutputStream) implicit def asPrintWriter(out: Writer): PrintWriter = new PrintWriter(out) implicit def read(s: String): Reader = new StringReader(s) }
2. Composing inheritance
У меня там был определён метод log(msg: String) = println(msg); но это как-то слишком примитивно, хорошо для repl, но не для сервлета, ну и т.д. Josh Suereth учит - а вы выдерните всю эту хрень в трейты:
trait Logging { def log(message: String) } trait SimpleLogging extends Logging { override def log(message: String) = println(message) }
И пишите типа
trait Connector extends Logging { ...
А в конкретных классах можно писать
object ViaPipe extends Connector with SimpleLogging { ...
class ViaServlet extends HttpServlet with Connector { ...
Цимес в том, что
HttpServlet
уже имеет у себя в кишках какой-то log(...)
; ну так туда весь логгинг и пойдёт. А в первом случае - пойдёт на нашего логгера. Вполне, по-моему, практичный способ присоседиться без лишнего траха.