P
P
Pe3oHaHc2013-10-18 16:36:20
Java
Pe3oHaHc, 2013-10-18 16:36:20

How to restrict a method call to the owner of an object?

Good afternoon! I'm writing a small Java framework based on the actor model that provides simple thread interaction.

I have an unusual problem! I need some method of an object to be called only from its container object.

The bottom line is this: I have an Event object (event). Other characters (threads) can subscribe to the event using the subscribe() method, when the event occurs, all these characters receive a notification about it. Those. the subscribe() method must be open to all characters in the program (for all threads). There are no problems with this - the public modifier solves it.
In turn, the Event.addReaction() method adds a reaction to the event, which must be immediately executed by the owner character of the event. This method must be accessedonly the owner of the event, because it is impossible for the characters to react to other people's events in any other way than after receiving the message.

Here is a piece of exaggerated code:

class Person
{
   Event mItDone = new Event();

   public Person()
   {
       mItDone.subscribe(AnotherPerson);       //AnotherPerson получит сообщение при наступлении события

       mItDone.addReaction(new myReaction());    //myReaction будет выполнено сразу при наступлении события
   }

   private void eventOccurs()
   {
       mItDone.fire();                //Запускает событие (fire не должен быть доступен ни для кого кроме этого экземпляра Person
   }

   class myReaction extends Reaction
   {
      react()
      {
           //Реакция этого персонажа на событие mIdDone;
      }
   }
}


So it turns out that for the correct functioning of an object of the Event class, I need the addReaction () and fire () methods to be available only for the object in which it is contained. Some special access modifier would help, but there are none (

Any thoughts?

Answer the question

In order to leave comments, you need to log in

6 answer(s)
M
mayorovp, 2013-10-18
@Pe3oHaHc

Option one - minimal protection from the Indian:

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

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

The owner of the event creates an object of the OwnedEvent class, but before passing it on to other objects, results in an Event. When you try to bring the event back, it hurts to beat on the hands.
Option two - maximum protection against the Indian, 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 with this approach, the Event.Owner class must have access to the private fields of the Event class, which can be used.
PS I haven't written anything in Java for 4 years, I can screw up with the syntax. I hope this does not interfere with the understanding of what is written.

S
sigod, 2013-10-18
@sigod

If I understand correctly, you don't want other objects to be able to call mItDone.addReaction()on Person? Then why not mark mItDoneit as private, but Personmake an interface for third-party objects, for subscription?

T
Tully, 2013-10-18
@Tully

I think there is some confusion here. The private/public modifiers are needed at the time of writing the code, in order to check that programmers understand the tasks correctly.
They are not needed at runtime. It is impossible to mark instances of these classes somehow at the time of writing classes using keywords.
If you need to distinguish Person instances from each other (for example, so that one reacts to an event, and the rest do not), create a field with a unique identifier in this class and check access rights based on them at runtime.

A
Alexey Kamchatkin, 2013-10-18
@PoN

make an Event interface, with addReaction(), fire() methods, then make classes inherited from Person and implement the Event interface. It turns out that the classes that implement Event will have these methods, and those who do not, will not. if I understand correctly. See also the Observer pattern.

S
sigod, 2013-10-19
@sigod

(answer has been deleted)

R
relgames, 2013-10-29
@relgames

Why not simplify to:

class Person {
   private void eventOccurs()    {
       react();
       AnotherPerson.react();
   }

   private react()  {
           //Реакция этого персонажа на событие mIdDone;
    }
}

Well, or if you really want through 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() { // Теперь никак нельзя вызвать fire() - ни через приведение типов, ни через рефлексию. 
            @Override
            public subscribe(Actor a) {
                fullEvent.subscribe(a);
            }
        }
    }
    ....
}

UPD above gave a similar solution.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question