Внедрить неявные методы/поля в анонимную функцию

Я только начинаю работать с Scala и застрял, пытаясь создать один конкретный объект.

У меня есть объект IdentifierFactory, который я хочу использовать для создания экземпляра Identifier. Я определил это так:

object IdentifierFactory {
    def apply(f: => Any):Identifier = {
        f; validate

        Identifier(...)
    }

    def validate:Unit = ???
}

Я хочу иметь возможность использовать его следующим образом:

IdentifierFactory {
    setName("name");
    addResource(resource);
}

Как я могу объявить свои setName и addResource (или, альтернативно, var, к которым у меня есть доступ), чтобы они были видны только в анонимной функции?


person Bart Platak    schedule 10.03.2015    source источник
comment
Не уверен, что означает это последнее предложение. Вы хотите получить доступ к результатам setName и addResource? Если да, не могли бы вы привести пример того, как бы вы их использовали и как validate вступает в игру?   -  person Michael Zajac    schedule 10.03.2015


Ответы (1)


Вы можете передать конструктор в свою анонимную функцию:

IdentifierFactory { b =>
    b.setName("name")
    b.addResource(null)
}

object IdentifierFactory {
    trait Builder {
       def setName(name: String)
       def addResource(r: Any)
    }

    case class Identifier(name: String, rs: List[Any])

    def apply(f: Builder => Any):Identifier = {
        var nm = "default"
        var rs = List[Any]()
        f(new Builder {
           def setName(name: String) = nm = name 
           def addResource(r: Any) = rs ::= r
        })
        validate

        Identifier(nm, rs)
    }

    def validate: Unit = {}
}

scala> IdentifierFactory { b =>
 |         b.setName("name")
 |         b.addResource(null)
 |     }
res4: IdentifierFactory.Identifier = Identifier(name,List(null))

Кстати, вы все еще можете сделать то же самое, просто передав имя и список ресурсов в функцию со значениями по умолчанию:

object IdentifierFactory {
    case class Identifier(name: String, rs: List[Any])

    def apply(nm: String = "default", rs: List[Any] = List[Any]()): Identifier = {          
        //validate it right here    
        Identifier(nm, rs)
    }

}

scala> IdentifierFactory()
res7: IdentifierFactory.Identifier = Identifier(default,List())

scala> IdentifierFactory(rs = List(null))
res8: IdentifierFactory.Identifier = Identifier(default,List(null))

scala> IdentifierFactory("nm", List(null))
res9: IdentifierFactory.Identifier = Identifier(nm,List(null))

scala> IdentifierFactory("nm")
res10: IdentifierFactory.Identifier = Identifier(nm,List())

Я бы также рекомендовал возвращать Option или Either вместо исключения проверки.

person dk14    schedule 10.03.2015
comment
отлично, именно то, что мне было нужно :) Спасибо за совет re/ Option/Either тоже! :) - person Bart Platak; 12.03.2015