2013-08-05 3 views
2

구성원 개체를 private로 만들려면 어떻게해야합니까? ? 즉,이 개체는 값을 읽고 수정할 수 있지만 같은 클래스의 다른 개체는 읽을 수 없습니다.Java에서 객체 수준 개인 액세스를 구현하는 방법

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 
    } 
} 

나는 자바의 '개인의 접근이 클래스의 코드로 제한됩니다 접근을 의미 이해합니다. 개념적으로 클래스의 모든 코드가 내 통제하에 있으므로 이에 대한 책임이 있습니다. Person 객체가 다른 Person 객체에 대해 수행하는 작업을 제어하는 ​​것은 필자의 책임이다.

하지만 다른 사람과 상호 작용하는 많은 메소드가 있고 컴파일러가 개인적으로 코드를 샅샅이 뒤져 보지 않고 나를 확인하기를 원합니다. 어쩌면이 자바 파일은 동료들과 공유되고 자주 변경됩니다.

내 질문은 - 어떻게 구현할 수있는 '이 개체에 비공개'액세스 자바에서? 그것을 달성하기위한 정상적이고 합리적인 방법이 있습니까?

편집 - 목표

내가이 인스턴스에 속하는 bankBalance 읽기/쓰기 할 수없는 다른 사람의 오브젝트를 보장하기 위해, 클래스 디자인/몇 줄의 코드를 원하는 재 강조. 나는 Java 용으로 설계된 것이 아니라는 것을 알고 있습니다. 그러나 이것이 일반적인 목적을 달성하는 가장 깨끗한 방법이 무엇인지를 보여주는 동기 중 하나입니다. 필자는 컴파일러가이를 수행하기를 원합니다. 모든 함수를 감사하고 올바른 getter/access 메소드 만 호출하는 솔루션을 찾고있는 것은 아닙니다.

+0

이렇게하려면 AOP를 사용할 수 있습니다. getter 및 setter에게 Exception을 발생 시키거나 기본값을 반환하도록 알려줍니다. 이것은 누가/무엇이 메소드를 호출 하는지를 알기 위해 어떤 보안 계층을 요구할 것이다. 스레드 로컬이 도움이 될 수 있습니다. –

+0

@Sotirios - 요점은 Java 'private'설정으로 getters와 setter를 통해 코드가 실행된다는 것입니다. 예 : function interact1에서 코드가 입력 매개 변수의 private 멤버에 직접 액세스하지 못하도록 막을 수 없습니다. –

+0

개인 필드가 포함 된'Person'의 수퍼 클래스를 만들 수 있습니다. 그런 다음 속성과의 모든 상호 작용이 게터와 세터를 통과하도록 'ManagedPerson'을 만듭니다. AOP에 대한 주석을 달거나 알베르토 (Alberto)가 대답 한 것과 같은 것을 할 수 있습니다. –

답변

0

각 인물 저울을 포함 할 저울의 arraylist를 선언 할 수 있습니다. 이 같은 뭔가 : 당신이 코드를 가지고 때마다

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)); 
} 

는 다음과 상호 작용하는 bankBalance 당신은 단지 그것을 호출 인스턴스로 같은 요소를 반환합니다.

예를 들어 다섯 번째 인스턴스가 균형을 잡으려고 시도하면 메서드는 배열의 다섯 번째 균형을 반환합니다. 예를 들어

는 :

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

이 그렇게 자신의 은행 잔고를 얻기 위해 시도하는 사람이 자신의 균형을 반환 전용 할 것입니다, 그들은 누구를 elses 균형을 볼 수 없습니다.

+0

각 인물마다 별도의 은행 잔액을 갖고 싶습니다. bankBalance –

+0

이 방법은 thisInstance가 항상 인물을 참조하기 때문에 작동하지 않습니다. 메서드가 호출되고 있으며, 메서드를 호출하는 인스턴스가 아닙니다. 그 또는 내가 뭔가 잘못 읽고 있어요 ... – SamYonnou

+0

수정 된 코드를 참조하십시오. – Undefined

0

나는 당신이 취하는 방향이 올바른 것이라고 생각하지 않습니다. 만약 당신이 내가 다른 각도에서 사물을 보려고한다면 그것은 당신이 요구하는 이상한 요구입니다.

필요한 경우 다른 개체의 속성 액세스를 금지 할 수는 없습니다. getter를 지정하고이를 사용하여 속성을 참조 할 수 있습니다.

인스턴스는 해당 속성으로 식별되므로 특정 속성을 확인한 다음 해당 인스턴스를 사용하여 특정 개체가 해당 속성 접근 자에 액세스 할 수 있는지 여부를 확인할 수 있습니다.

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


      //rest code here 
     } 

가 작동 희망 ...

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? 
    } 
} 
+0

이것은 개체 생성을 제어하는 ​​엔티티에 따라 다릅니다. –

+0

무엇을 의미합니까? 이것이 당신의 의견으로는 효과가 없을 것 같습니까? –

+0

'isBankBalanceAccessible()'에서 어떤 검사가 수행되는지에 따라 달라질 것입니다. 이러한 속성은 사용자가 제어 할 수 있어야합니다. –

0

내가이 생각을 .. !! :

는 그래서 이런 식으로 뭔가 될 것 정리해

+0

더 나은 방법은 Object 클래스 equals 메서드를 사용하여 비슷한 ID의 객체를 확인하는 것입니다 ... !! –

0

모두가 지적했듯이이를 수행 할 실제 방법이 없습니다. 당신은 모든 액세스가 object.getBankBalance(this)을 통해 수행 할 수 있음을 시행하는 형태로 다음

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

과의 게터처럼 뭔가를 할 수 있습니다.

그러나 이는 사용자가 bankBalance에 직접 액세스하거나 object.getBankBalance(object)에 전화하는 것을 중단하지 않습니다.

4

목적이 아니라 악의보다는 사고를 방지하는 것입니다 가정하면, 당신은 균형을 소유 한 사람을 추적 유지하는 별도의 BankBalance 클래스를 만들 수 있습니다 getBalance의 모든 사용 this을 통과 발신자를 필요

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) ... 
    } 
} 

을 . 나는 이것이 실수로 에 더 어려워 질 것이라고 생각한다. 다른 사람의 저울을 억세스하는 코드를 작성하라. BankBalance를 중첩 된 클래스로 만들 수도 있고 belongsTo 필드가 명시 적으로 필요하지 않고 calledBy != Person.this 필드를 검사 할 수 있지만 interact1person2.bal.bal을 참조 할 수 있습니다. BankBalance에서 bal private을 지정하면 캡슐 클래스가 액세스하지 못하게됩니다. 어쩌면 사고 예방에 충분할 수도 있습니다.

+0

+1 인터페이스가 마음에 들었습니다. 오브젝트를 전달하고 정확한 밸런스를 되 찾으십시오. 아직도 만족스럽지 못하며, 모호함에 의한 보안과 더 비슷합니다. person.dontLookAtThis.noReallyThisMeansYou.bankBalance라는 내부 클래스를 중첩 할 수 있습니다. 이렇게하면 개발자가 실수로 호출하는 것을 방지 할 수 있습니다. 몇 줄의 코드/디자인으로 컴파일러가 나를 확인하고 읽기/쓰기를 보장하지 못하는 솔루션을 찾고 있습니다. –

+0

-이 솔루션의 문제점은 BankBalance 및 BankBalance.bal을 내 개체의 개인 멤버로 계속 사용할 수 있다는 것입니다. 그래서 '다른 사물이 내 사적인 영역에 접근 할 수있다'는 문제는 여전히 존재합니다. 단지 레벨을 더 깊게 감쌌습니다. –

+0

"무명의 보안"이란 일반적으로 고의적 인 공격으로부터의 보호를 말합니다. 코드에 액세스 할 수 있지만 범죄 목적으로 기꺼이 사용하려는 프로그래머가 있다면 프로그래밍 방식의 솔루션이 없다고 생각합니다. 새로운 언어 기능조차도 도움이되지 않습니다. 코딩 오류를 방지하기 위해 특정 종류의 오류를 범하기 어렵게 만들면 충분합니다. 그러나, 당신이 요구하는 종류의 언어 기능을 추가하는 것이 타당합니다. 나는 미래의 변화를 제안 할 수있는 좋은 곳이 어디인지 궁금합니다. – ajb

0

java에는 "object-private"이 없습니다. 객체가 같은 클래스의 다른 객체에 대한 참조를 얻으면 내부 상태에 액세스 할 수 있습니다.

따라서 다른 개체에 대한 참조가있는 경우 클래스의 인스턴스가 동일한 클래스의 다른 인스턴스에 대한 개인 필드 또는 메서드에 액세스하지 못하게 할 수 없습니다.

죄송 합니다만 내부 액세스를 처리하는 것은 개발자의 책임이며 동료가 잘못된 조치를 취한 경우 대화를 나누거나 실패한 테스트를 작성하십시오. java에 "object-private"필드를 표시하는 기능이 있더라도 동료가이 표시를 제거하지 못하게 막지는 못합니다.

관련 문제