How to limit method call to the object's owner?

Good day! I am writing a small framework in Java, based on the actor model and provides a simple interaction flows.

I'm having an unusual problem! I need some method of an object could be caused only from its container object.

The bottom line is this: I have an Event object (event). At the event, using the method subscribe() to subscribe to other characters (streams) when the event occurs, all these characters get a notification. Ie the method subscribe() must be open for all characters in the program (all threads). This is no problem — it's a public modifier.
In turn, the Event.addReaction() adds to event response, which must be immediately implemented character-the owner of the event. Access to this method should have only the owner of the event, because it is impossible to have the characters react to other people's events not otherwise except when you receive a message.

Here is an exaggerated piece of code:

class Person
{
 MItDone Event = new Event();

 public Person()
{
 mItDone.subscribe(AnotherPerson); //AnotherPerson will receive a message when the event occurs

 mItDone.addReaction(new myReaction()); //myReaction will be executed immediately when the event occurs
}

 private void eventOccurs()
{
 mItDone.fire(); //Triggers the event (fire should not be accessible to anyone besides the Person instance
}

 class Reaction extends myReaction
{
react()
{
 //Reaction of this character to the event mIdDone;
}
}
}


It turns out that I for the correct functioning of the object of the Event class methods need to addReaction() and fire() was available only for the object that contains it. Would any special access modifier, but there are none(

What are your thoughts?
October 3rd 19 at 03:22
6 answers
October 3rd 19 at 03:24
Solution
The first one is minimal protection from the Hindu:
class Event {
 public void subscribe(...) {}
}

class OwnedEvent extends Event {
 public void fire(...) {}
 public void addReaction(...) {}
}

The owner of the event creates an object of class OwnedEvent, but before you transfer it to other objects leads to the Event. When you try to bring events back — to devastate the hands.

The second option — maximum protection from Hindu, but with increased memory consumption.
class Event {
 public void subscribe(...) {}

 public static class Owner {
 private final Event Event = new Event();

 public void fire(...) {}
 public void addReaction(...) {}

 public Event getEvent() { return event; }
}
}

The point is that in this approach the Event class.The Owner should have access to the private fields of the Event class, and you can use.

PS in Java did not write anything for 4 years, can screw with syntax. I hope this will not prevent the understanding written.
The second option is somewhat obscure, but the first option I like. You can make OwnedEvent private to the owner class that will prevent creating objects of this class outside of it. Thank you! This is gorgeous) - fern_Hahn commented on October 3rd 19 at 03:27
To do EventOwner private I would not recommend it, because then the events can only possess people, but not the kettle. And the kettle can be your event. It is better to try to understand the second option, or leave public EventOwner. - Cindy_Huds commented on October 3rd 19 at 03:30
Something is not very clear how you are going to access is not a static Event from a static subclass? Yes, a private field with Event I see, but in this case you system will not be more than one owner events. - Tevin99 commented on October 3rd 19 at 03:33
Please note: private field event is not is static. - Cindy_Huds commented on October 3rd 19 at 03:36
Mm, fifteen minutes staring at the second example. Either something is not right or I brake) I can't understand how to apply the objects of these classes. In the class that owns the event I have to create a public Event and private Event.Owner? Maybe then you should make the Owner of inner class is static?

class Event
{
 public void subscribe(...){}

 public class ForOwner
{
fire(...){}
addReaction(...){}
}
}


If so, this method is less curve than everyone else) Try it. - fern_Hahn commented on October 3rd 19 at 03:39
Like this (modified your code):
class Person
{
 private final Event.Owner mItDone = new Event.The Owner();

 public Person()
{
 mItDone.addReaction(new myReaction()); //myReaction will be executed immediately when the event occurs
}

 private void eventOccurs()
{
 mItDone.fire(); //Triggers the event
}

 public Event getEvent()
{
 return mItDone.getEvent(); // Provided by other classes the opportunity to subscribe to the event.
}
}
- Cindy_Huds commented on October 3rd 19 at 03:42
And making a class domestic Owner is impossible, because then anyone can create a new Ownerа for the event.
There is an option to make the inner class Event, in relation to Ownerу, but I think they are not so beautiful. - Cindy_Huds commented on October 3rd 19 at 03:45
mayorovp, Yes, you are right. Confused with the static subclass in the class. Plus for the idea. - Tevin99 commented on October 3rd 19 at 03:48
Mm, yeah, it's working without the interface like HasEvents still not enough, since it is necessary to have all relevant event classes were available a method getEvent(). It's sad(

I was thinking we could go the other way. I can provide validation for access in the event if the Event object will know which object they are, and the methods addReaction() and fire() will know which object they are invoked. And if the environment does not allow to provide them with this information at compile time you can do it at runtime. Will get something like:

class Event
{
 private Object mContainer;

 public Event(Object container) { mContainer = container; }

 public void fire(Object caller) { /*check that mContainer is equal to the caller. If that - to throw an exception. */ }
 public void addReaction(Reaction reaction) { /* check which contains the reaction and what type of mContainer and act accordingly.*/ }
}
class Reaction
{
 Object mContainer; 

 public Reaction(Object container) { mContainer = container; }
 public abstract void react(...);
}


With such a scheme will have to agree to pass this to the constructors of Event and Reaction to the fire () method to give the Event have the right information. It's not perfect, but close to what I wanted. Yes, of course, instead of this you can pass something else, and in this case everything goes down the drain, but on reflection I realized that I like this option as I write this framework in order to test new concepts and if I'm going to put it into production so only as part of something bigger. So I'm more important than ease of use and minimizing possible errors. Thanks, without you it would be harder) - fern_Hahn commented on October 3rd 19 at 03:51
Mm, yeah, it's working without the interface like HasEvents still not enough, since it is necessary to have all relevant event classes were available a method getEvent().
You something strange has come up, and now solve a non-existent problem.

You also don't have a goal "to subscribe to all events of an arbitrary object"? Instead, you have a problem "subscribe to the specific event in the Person class". The interface here is not needed, unless you are going to subscribe to events from configuration file.

And the option that you came up with — nothing. No one hurt Hindu person is to pass this as the argument. - Cindy_Huds commented on October 3rd 19 at 03:54
OK, but when a Person has a lot of events? To do for each method receive the event + object's inside?
About my version again, for me the main convenience of use. The problem for me was not to make maximum protection from the Hindu, and to allow me to quickly and easily create events from different objects and is fast and simple to subscribe. And the tricky part was that I myself, and not Indian, you could do it for the event and those who cannot be signed, and, of course, do not ignore it. And then long and hard to find why do I get the threads to interfere with each other and spoil the results. The option that I suggested, my problem is solved :) I May have not clearly stated their wishes in the beginning, for that I apologize. I first resorted to a similar resource and is not taught to properly Express the problem. But I'll get better I hope :) - fern_Hahn commented on October 3rd 19 at 03:57
Convenience say? But what if your code returns an Objectthat can be Personand may not be? As code can subscribe to events of this object? Unless of course the object is able to create events. - Tevin99 commented on October 3rd 19 at 04:00
Mm, the object may contain events. But to dynamically create them, nobody can. And in the case of Object I use instanceof to check whether an object is a Person, om or not.
Do support the events would not hurt the language. In C# like this. If she and Java would not have had to suffer so. - fern_Hahn commented on October 3rd 19 at 04:03
Although I think you understand correctly... what do you mean by "code can subscribe to events and code returns an Object"? Which object do you mean "code"? - fern_Hahn commented on October 3rd 19 at 04:06
And in the case of Object I use instanceof to check whether an object is a Person, om or not.
What will you do if you have an object of unknown type, and you need to subscribe to its events? - Tevin99 commented on October 3rd 19 at 04:09
Mm, I don't need to know what type of object that adds the kind of reactions to the event. I just need to know if it is a character or not.

If it's a character, I need to check whether he is the owner of the event and if so, then subscribe. As the event and the response contain a reference to the container object, it becomes possible.

If this object, I need to make sure that there is no attempt to add to its event character's reaction — this would lead to interference in the personal space of the character. However, if you subscribe to the event object attempts another object (not a character) to allow him that. - fern_Hahn commented on October 3rd 19 at 04:12
October 3rd 19 at 03:26
If I understand you correctly, you want the other objects could cause mItDone.addReaction() from Person? Then why not mark mItDone as private, and in Person to make an interface for third-party objects for a subscription?
Yes, that's what I want. It is necessary that methods addReaction() and fire() would cause only the owner of the event object.
What you have to offer almost perfect. But there is one caveat. An object of type Event may be present not only in the Person class. It can be any object in the system. And implement each extra interface will be uncomfortable. Besides, I don't want to restrict access to the event because it would complicate the syntax of working with them. - fern_Hahn commented on October 3rd 19 at 03:29
Such an interface can be done through inheritance.

Create a base class, for example, EventEmitter. In it, create the necessary methods: subscribe , mark as publicand addReaction and fireprotected.

Then takedaite Person from EventEmitter: public class Person extends EventEmitter.

And voila. Now external classes can only call method subscribe, others remain they are not available.

In fairness, it should be noted that classes in the same package with the EventEmitter will still be able to call hidden methods. Because in Java you cannot allow access to sub-classes and prohibit for package: access control. - Cindy_Huds commented on October 3rd 19 at 03:32
It is not good to inherit what the object is. Person it is still "the man" and he could derive from, for example, the class Human. In addition, the event can contain any object and if it's already something inherited this scheme is collapsing. But in General the idea is correct. All this is done through the interface. Only here look this all is not simple( - Tevin99 commented on October 3rd 19 at 03:35
Then make the EventEmitter interface, write the base implementation — BaseEventEmitter, from which derive when can. When not — implement interface EventEmitter. - Cindy_Huds commented on October 3rd 19 at 03:38
This option will work, do not argue. But it is quite time-consuming. Have to enter the event IDs to inherit all root objects from the base class to implement manually every time the interface where it did not happen to inherit a base class. Too much of a hassle) also, if there is something else in the event that apply this schema will not work again — have to get crutches. I'll try the method from an internal class, but thanks for trying) - fern_Hahn commented on October 3rd 19 at 03:41
October 3rd 19 at 03:28
I think there is some confusion. The modifiers private/public need at the time of writing the code to check that the programmers understand the tasks.
In runtime they are not needed. Mark-at the moment of writing classes instances of these classes with the help of key words it is impossible.
If you want to distinguish between Person instances from each other (for example, one responded to the event and no one else) make this class a field with a unique identifier and verify the runtime access rights based on them.
Well, the access rights between the characters I can distribute. I can check in the method if the thread that created the event is trying to execute these methods. But we still have a problem with objects that are not characters. For example, the electric kettle has an event "water boiled". This event may only be initiated by the kettle, but the "subscribe" and follow him to anyone in the room. And it turns out that the maker has full access to the event, and the people in the room can only subscribe to the event.
All this can be achieved through interfaces, but it will be very inconvenient to use. I'd really like to work with the event was enough just to add it to the class. Although I begin to suspect that this is impossible( - fern_Hahn commented on October 3rd 19 at 03:31
October 3rd 19 at 03:30
make an interface Event, with the methods addReaction(),fire(), then make the classes inherit from Person and implement the Event interface. It turns out classes realisatie Event will have these methods and those who no. if properly understood. Also see Observer pattern.
Mm, but, there is one event may be several. Will have to do almost as in this pattern, but to make two interfaces for event subscription and to add the reaction. At the same time to check if I'm trying to add a character reaction to an event object, and not if I'm trying to add the reaction of one character to the other event. - fern_Hahn commented on October 3rd 19 at 03:33
October 3rd 19 at 03:32
(the answer was deleted)
October 3rd 19 at 03:34
Why not simplify to:
class Person {
 private void eventOccurs() {
react();
AnotherPerson.react();
}

 private react() {
 //Reaction of this character to the event mIdDone;
}
}


Or if you really want through the events:
public interface Event {
 void subscribe(Actor a);
}

public interface FullEvent extends Event {
 void fire();
 void addReaction(...)
}

public class Person {
 private final FullEvent fullEvent = new FullEventImpl();

 public getEvent() {
 return new Event() { // Now, no way to call fire() - neither through coercion nor through reflection. 
@Override
 public subscribe(Actor a) {
fullEvent.subscribe(a);
}
}
}
....
}


UPD brought up a similar solution.
Again, events can contain not only characters, but also objects. In this case, your option involves the writing of repetitive code. - fern_Hahn commented on October 3rd 19 at 03:37

Find more questions by tags ProgrammingJava