简体   繁体   中英

how to implement object-level private access in java

How could I make a member field private to this specific object ? ie this object can read and modify the value, but other objects of the same class cannot.

eg

class Person 
{
    // don't mind sharing these with other persons :
    private integer houseNumber;
    private integer telephoneNumber;

    // would like this to be *really private*
    // (only visible / modifiable to this instance)
    private integer bankBalance;


    // Lots of code for interaction with other persons:
    // (e.g. maintained by co-workers)

    void interact1(Person person)
    {
        //Lots of code
    }

    void interact2(Person person)
    {
        //Lots of code
    }

    //...

    void interactN(Person person)
    {
        //Lots of code
    }
}

I understand that Java's 'private' access means access is restricted to code in this class. Conceptually all the code in the class is under my control so I am responsible for it. It should be my responsibilty to control what Person objects do to other Person objects.

But say I have a large number of methods interacting with other persons, and I want the compiler to do the checking for me, rather than personally scouring the code. Maybe this java file is shared with co-workers, and changes frequently.

My question is - how can I implement 'private to this object' access in Java? Is there a sane / sensible way of achieving it?

EDIT - re-emphasis of goals

I want a few lines of class design / code, to guarantee that other Person objects can not read / write the bankBalance belonging to this instance. I know it's not really designed for in Java - but that's part of my motivation, to see what is the cleanest way to achieve it in general. I really want the compiler to enforce it - I'm not looking for a solution that involves auditing all the functions, making sure they only call the correct getter / access method.

Assuming your purpose is to protect against accidents rather than malice, you could create a separate BankBalance class that keeps track of who owns the balance:

class BankBalance {
    private int bal;
    private Person belongsTo;
    public BankBalance (int initialBalance, Person belongsTo) {
        this.bal = initialBalance; this.belongsTo = belongsTo; 
    }
    public int getBalance (Person calledBy) {
        if (calledBy != belongsTo) throw new RuntimeException ("no peeking");
        return bal;
    }
}

class Person {
    private BankBalance bal;

    void checkBalance () {
        if (bal.getBalance(this) > 1000) ...
    }
}

Any use of getBalance would need the caller to pass this . I think this might make it harder to accidentally write code that accessess another Person's balance. You could also make BankBalance a nested class, and check calledBy != Person.this rather than needing an explicit belongsTo field, but that would allow interact1 to refer to person2.bal.bal (making bal private in BankBalance still wouldn't prevent the enclosing class from accessing it). Maybe that's still good enough to prevent accidents.

As everyone pointed out there is no real way of doing this. You could do something like a getter of the form

private int getBankBalance(Object caller) {
     if (caller == this) {
          return bankBalance;
     } else {
          throw new RuntimeException("GTFO");
     }
}

and then enforcing that all access be done through object.getBankBalance(this) .

However this does not stop people from accessing the bankBalance directly or calling object.getBankBalance(object) .

You can declare an arraylist of balances that will contain each Persons balance. Something like this:

static int instances = 0;
private int thisInstance = 0; 
private List<Integer> balances = new Arraylist<>();

public Person() {
   instances++;
   thisInstance = instances;
   balances.add(thisInstance, new Integer(0));
}

Then whenever you have code that interacts with the bankBalance you just return the same element as the instance that called it.

For example, if the fifth instance tried to get it's balance, the method would return the fifth balance in the array.

For example:

private int getBankBalance() {
   return balances.get(thisInstance).intValue();
}

This will make it so anyone attempting to get their bank balance is only returned their balance, and they can't see anyone elses balance.

I don't believe that the direction you are taking is the correct one, if I were you I would try to see things from a different angle, it is a weird requirement the one you're asking.

You cannot achieve that if what you need is forbid the property access from other objects. You could do it if you specify a getter for it and use that to reference the property.

An instance is identified by its attributes, so you could write a method that checks for certain properties and then use it to determine if a certain object could access that property accessor.

So to sum up it would be something like this:

private boolean isBankBalanceAccessible() {
    // check that properties are those you want,
    // for example only when houseNumber is 1234567890
    return houseNumber == 1234567890;
}

private int getBankBalance() {
    if (isBankBalanceAccessible()) {
        return bankBalance;
    } else {
        // maybe throw here?
    }
}

I thought of this...

     void interact1(Person person)
      {
         if(this==person)
          {
             person.bankBalance
             // Do here with the balance of the objecct which calls this function
          }


          //rest code here
      }

Hope it works..!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM