2014-12-16 2 views
0

하나 이상의 차원에서 입자 충돌을 시뮬레이트하는 프로그램을 작성하려고합니다. 2D 케이스의 경우, 입자를 보여주는 GUI를 만들고 싶습니다.참조 변수로 배열 캡슐화

메인 클래스 , 내부 클래스 Particle, 상기 배열 Particles, 그리고 입자의 위치와 속도를 업데이트하는 몇 가지 방법이 있습니다. 이 클래스는 대략 다음과 같습니다 : 나는 목적을 그리기 위해 자신의 위치와 반경을 찾을 수 있도록 그래픽 클래스에서

class ParticleCollider { 

    class Particle { 
      private double mass; 
      private double[] pos; 
      //plus some other private class variables 
      public Particle(double mass, double[] pos) { 
       this.mass = mass; 
       this.pos = pos; 
      } 
    } 

    private Particle[] pArray; 

    //Details of constructor are irrelevant 
    public ParticleCollider() { 

    } 

    //Do stuff to particles in pArray, i.e. change their positions and velocitites 
    public void update() { 
      //For example 
      pArray[0].pos[0] = 0; 
    } 

} 

, 내가 Particles에 액세스 할 수 있어야합니다. 물론 한 방법은 ParticleCollidergetParticles 메서드를 추가하여 Particles, pArray 배열을 반환하는 것입니다. 이것이 캡슐화의 위반으로 여겨지는지 궁금한 점이 있습니다. Particle 클래스에는 설정자가 없으므로 Particles을 변경할 수 없습니다. 또한 배열 hase 고정 길이 때문에 어떤 Particles 추가 할 수 없습니다. 내가 할 수있는 유일한 일은 꽤 나쁜 것인데, 다소 Particle을 가져다가 null의 값을 할당하는 것입니다.

편집 배열 대신 목록을 사용하고 해당 목록에 반복기를 제공하는 것이 좋습니다. 이것이 캡슐화 문제를 해결하지 못하는 것 같습니다. 어쨌든 배열 ParticleParticles 컬렉션에서 선택하고 주기적으로 반복 할 수 있어야하므로 배열을 포기하지 않아도됩니다.

+2

주'pArray'가 배열이기 때문에 그 . 반환하면 반환 된 요소가 마음대로 요소를 변경할 수 있습니다. 이 점이 걱정된다면, 'Particle' 생성자는 여전히 외부에서 수정할 수있는 참조를 저장한다는 점에 유의해야합니다. – 5gon12eder

+0

방법 : 배열 대신 목록을 사용하고 의도하지 않은 경우 목록을 수정하지 못하게 모든 입자 (Iterable)에 대한 중 간자를 제공합니다. –

+0

관련이 없지만 내부 클래스는 종속적이지 않으면 정적이어야합니다. Collider의 인스턴스에서. Collider 클래스 외부에서 사용하는 경우 (그렇기 때문에), 별도의 파일로 선언 할 수도 있습니다. – Joffrey

답변

1

방법이 패턴을 사용하는 방법에 대한 :

public class Particle { 
     // Particle code 
    } 

    public class Particles implements Iterable<Particle> { 
     ArrayList<Particle> myParticles = new ArrayList<Particle>(); 

     public void add(Particle particle) { myParticles.add(particle); } 

     public Iterator<Particle> iterator() { 
      return myParticles.iterator(); 
     } 

     // more code on particles 
    } 

    void bla() { 
     Particles particles = new Particles(); 
     particles.add(new Particle()); 
     particles.add(new Particle()); 

     for (Particle particle : particles) { 
      System.out.println("P="+particle); 
     } 
    } 

당신이이 패턴을 사용할 수있는이 반복자의 제거()을 억제하려면 :

public static class Particles implements Iterable<Particle> { 
     ArrayList<Particle> myParticles = new ArrayList<Particle>(); 

     public void add(Particle particle) { myParticles.add(particle); } 

     public Iterator<Particle> iterator() { 
      return new Iterator<Particle>() { 
       Iterator<Particle> listIterator = myParticles.iterator(); 

       @Override 
       public boolean hasNext() { 
        return listIterator.hasNext(); 
       } 

       @Override 
       public Particle next() { 
        return listIterator.next(); 
       } 

       @Override 
       public void remove() { 
        throw new UnsupportedOperationException(); 
       } 
      }; 
     } 

    } 
+0

감사합니다, 나는 그것이 효과가 있다고 생각합니다! 그러나 나는 왜 입자를 호출 할 수 없는지 궁금합니다 .iterator(). remove(). 그렇게하면 IllegalStateException이 발생합니다. 당연히 입자를 호출 할 수 있기를 원하지 않습니다 .iterator(). remove(), 나는 이것을 막지 못하게하는 것이 무엇인지 궁금합니다. –

+0

불행히도 remove()는 해당 반복자에서 작동합니다. iterator에서 next()를 호출하면 remove()가 가능합니다. 코드를 점검하고 Iterator API에서 IllegalStateException에 대한 설명을 확인하십시오. –

+0

remove() –