Use стать() из Java
Я использую Akka с Java. Согласно документации, context.become()
принимает Procedure<Object>
в качестве параметра. Фактически, он ожидает PartialFunction<Object, BoxedUnit>
, который, кажется, является автогенерированным с множеством методов со странными именами.
Каков правильный способ использования функции get() из Java?
PS я использую Akka 2.0.3
Обновление:
Похоже, существуют два метода: context() и getContext(). Первый возвращает ActorContext, а второй возвращает UntypedActorContext. UntypedActorContext имеет become(Procedure<Object>)
.
Ответы
Ответ 1
Вы вводите в заблуждение Akka Java и Scala API. Технически вы можете использовать Scala библиотеки, такие как Akka, из Java-кода, но довольно часто это многословно и громоздко. Поэтому команда Akka решила разработать отдельные API-интерфейсы - родные в Scala и Java-адаптере.
В Scala API вы расширяете akka.actor.Actor
, у которого есть поле context
типа akka.actor.ActorContext
. Этот ActorContext.become()
принимает PartialFunction
, который является Scala -специфическим классом.
С другой стороны, в Java API вы расширяете akka.actor.UntypedActor
, имея (Java-подобный) метод getContext()
, возвращая akka.actor.UntypedActorContext
. Этот принимает akka.japi.Procedure
.
Чтобы сократить длинную историю - если вы используете Java API, придерживайтесь ее. Существует четкое различие между документами Scala и Java.
Ответ 2
Есть много хороших примеров того, как это сделать в java. Надеюсь, этот пример поможет:
Procedure<Object> angry = new Procedure<Object>() {
@Override
public void apply(Object message) {
if (message.equals("bar")) {
getSender().tell("I am already angry?", getSelf());
} else if (message.equals("foo")) {
getContext().become(happy);
}
}
};
Procedure<Object> happy = new Procedure<Object>() {
@Override
public void apply(Object message) {
if (message.equals("bar")) {
getSender().tell("I am already happy :-)", getSelf());
} else if (message.equals("foo")) {
getContext().become(angry);
}
}
};
public void onReceive(Object message) {
if (message.equals("bar")) {
getContext().become(angry);
} else if (message.equals("foo")) {
getContext().become(happy);
} else {
unhandled(message);
}
}
}
Ответ 3
Вкратце, при использовании Java API
убедитесь, что вы вызываете метод getContext()
вместо context()
, который предназначен для использования с Scala API
.
Оформить заказ это (Java)
@Slf4j
@RequiredArgsConstructor
public class Greeter extends AbstractActor {
private final ActorRef printer;
public static Props props(ActorRef printer) {
return Props.create(Greeter.class, printer);
}
@Override
public Receive createReceive() {
return withWhomToGreet(""); // initial state
}
private Receive withWhomToGreet(String name) {
return receiveBuilder()
.match(WhoToGreet.class, // changing actor state context
whoToGreet -> getContext().become(withWhomToGreet(whoToGreet.getWho())))
.match(Greet.class, greet -> {
String msg = format("Hola, %s", name);
log.info("sending {} to {}", msg, printer);
printer.tell(Greeting.of(msg), self());
})
.matchAny(o -> {
log.error("unexpected: {}", o);
unhandled(o);
})
.build();
}
}
или это (kotlin)
class CounterActor : AbstractActor() {
companion object Factory {
sealed class Commands {
override fun toString(): String = javaClass.simpleName
object Increment : Commands()
object Decrement : Commands()
object GetState : Commands()
}
private val type = CounterActor::class.java
val props: Props = Props.create(type) { CounterActor() }
val name: String = type.simpleName
}
override fun createReceive(): Receive = withCounter(0) // init state
private fun withCounter(counter: Int): Receive =
receiveBuilder()
.matchAny { cmd ->
context.system.log().info("current: $counter, received: $cmd")
when (cmd) {
is GetState -> sender.tell("counter value: $counter", self)
is Increment -> {
// switch context with new updated actor state,
// actor is still stateless, similarly like we
// doing in scala for context.become
// Make sure with Java API you are calling
// getContext() method, not context()!
context.become(withCounter(counter + 1))
}
is Decrement -> // another change of actor state
context.become(withCounter(counter - 1))
else -> unhandled(cmd)
}
}
.build()
}
Все может быть сделано с той же идеей, как в Scala