ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [자바의 정석] Chapter07-2. 객체지향 프로그래밍2
    스터디플래너/공부하기 2022. 3. 1. 21:38

    1. 제어자(modifier)
      1. 제어자란?
        1. 제어자란 클래스, 변수, 메서드의 선언부에서 각각의 부가적인 의미를 부여하는 역할을 한다. public, default, protected, private 접근제어자와 그 외의 것들로 나눌 수 있다. 제어자는 하나의 대상에 여러가지로 조합하여 사용할 수 있으나 접근 제어자는 네 가지 중 하나만 사용할 수 있다.
      2. static - 클래스의, 공통적인
        1. static은 '클래스의', '공통적인'이란 뜻을 갖고있다. 클래스변수, 즉 static멤버변수는 하나의 변수를 모든 인스턴스가 공유하기 때문에 인스턴스와 관계 없이 같은 값을 갖는다. 
          제어자 대상 의미
          static 멤버변수 - 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다.
          - 클래스변수는 인스턴스를 생성하지 않고도 사용 가능하다.
          - 클래스가 메모리에 로드될 때 생성된다.
          메서드 - 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
          - static 메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다.
          초기화 블럭  
      3. final - 마지막의, 변경될 수 없는
        1. final은 '마지막의', '변경될 수 없는'의 의미를 가지고 있다. 변수에 사용하면 값을 변경할 수 없는 상수가 되고, 메서드에 사용하면 오버라이딩 할 수 없다. 클래스에 사용되면 자식클래스를 정의할 수 없다.
          제어자 대상 의미
          final 클래스 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다.
          확장할 수 없어 다른 클래스의 조상이 될수 없다.
          메서드 변경될 수 없는 메서드로 final메서드는 오버라이딩을 통해 재정의될 수 없다.
          멤버변수 변수 앞에 final을 붙이면 값을 변경할 수 없는 상수가 된다.
          지역변수
        2. 생성자를 이용한 final멤버 변수의 초기화
      4. abstract - 추상의, 미완성의
        1.  abstract는 메서드의 선언부만 작성하고 실제 수행할 내용은 구현하지 않는 추상 메서드를 선언한는데 사용된다. 
          제어자 대상 의미
          abstract 클래스 클래스 내에 추상메서드가 선언되었음을 의미한다.
          메서드 선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 의미한다.
      5. 접근 제어자(access modifier)
        제어자 같은 클래스 같은 패키지 자식 클래스 전체
        public O O O O
        protected O O O X
        (default) O O X X
        private O X X X
        1. 접근 제어자를 사용하는 이유는 클래스 내부에 선언된 데이터를 보호하기 위해서이다. 데이터가 유효값을 유지하고, 외부에서 함부로 변경할 수 없도록 외부로부터의 접근을 제한하는데 필요하다. 이는 데이터 감추기(data hiding), 객체지향 프로그래밍의 캡슐화(encapsulation)에 해당한다.
        2. 이를 위해 멤버 변수는 private를 사용하고, 메소드를 이용하여 값을 읽고 변경할 수 있도록 한다. 값을 읽는 메소드를 'get멤버변수 이름', 변경하는 메소드를 'set멤버변수 이름'으로 한다. 그래서 getter와 setter라 부른다.
        3. 생성자에도 접근제한자를 사용하여 인스턴스의 생성을 제한할 수 있다. 생성자의 접근제한자는 클래스와 같거나 다를 수 있다. 생성자의 접근제한자를 private로 지정하면 외부에서 생성자에 접근할 수 없어 인스턴스를 생성할 수 없다. private클래스는 같은 클래스 내에서 접근이 가능하므로 같은 클래스에서 인스턴스를 만들 수 있다. 이 인스턴스를 반환해주는 public메서드를 제공하면 외부에서 이 클래스의 인스턴스를 사용할 수 있다. 대신 public이면서 static이여야 한다.
          더보기
          학원에서 프로젝트할 때 사용한 코드이다. BasketVo클래스에서 basketNo라는 멤버변수는 private로 지정하고 setBasketNo(), getBasketNo() 메소드를 이용하여 값을 설정하고 변경할 수 있도록 하였다. BasketDao 클래스의 인스턴스를 private로 지정한 뒤 setDao()는 public void로 선언하여 사용했다. 덕분에 Dao클래스를 여러곳에 선언하지 않고 사용할 수 있게 되었다. 이는 GOF의 디자인 패턴 중 싱글톤 패턴이라 한다. 학원에서 프로젝트할 때, 싱글톤패턴을 많이 사용했다. 
          public class BasketVo {
          	private int basketNo;
              
          	public int getBasketNo() {
          		return basketNo;
          	}
          	public void setBasketNo(int basketNo) {
          		this.basketNo = basketNo;
          	}
              
          	public BasketVo(int basketNo) {
          		super();
          		this.basketNo = basketNo;
          	}
              
          	public BasketVo() {
          		super();
          	}	
          }
          
          
          @Repository
          public class BasketDao {
          
          	public int deleteBasket(int userNo, int basketNo) {
          		return DBManager.deleteBasket(userNo, basketNo);
          	}
              //...
          }
          
          @Controller
          public class BasketController {
          
          	@Autowired
          	private BasketDao dao;
          
          	public void setDao(BasketDao dao) {
          		this.dao = dao;
          	}
              //...
          	public void deleteBasket(HttpServletRequest request, HttpSession session, @RequestParam(value = "basket[]") List<Integer> basketItem) {
          
          		int userNo= (int)session.getAttribute("userNo");
          		for (int i = 0; i < basketItem.size(); i++) {
          			List<Integer> basketNo=dao.getBasketNo(basketItem.get(i));
          			for(int j=0; j<basketNo.size(); j++) {
          				dao.deleteBasket(userNo, basketNo.get(j));
          			}
          		}
          	}
          }
      6. 제어자(modifier)의 조합
        대상 사용가능한 제어자
        클래스 public, (default), final, abstract
        메서드 모든 접근 제어자, final, abstract, static
        멤버변수 모든 접근 제어자, final, static
        지역변수 final
        1. 메서드에 static과 abstract를 함께 사용할 수 없다. abstract는 메서드의 틀만 정한 추상 메서드의 제어자이고 static은 몸통이 있는 메서드에만 사용할 수 있다.
        2. 클래스에 abstract와 final을 동시에 사용할 수 없다. 클래스에 final이 있으면 더이상 상속할 수 없다, 즉 확장할 수 없다는 의미이고 abstract은 틀만 정해져 있고 상속을 통해 내용이 완성되므로 서로 모순된다.
        3. abstract메소드의 접근제어자가 private일 수 없다. abstract는 추상메서드로 추상 메서드가 속한 부모 클래스를 상속받은 자식 클래스에 의해 완성된다. private인 경우 
        4. 메서드에 private과 final을 같이 사용할 필요는 없다. 접근자가 private인 메서드는 오버라이딩 될 수 없으므로 둘 중 하나만 사용해도 충분하다.
    2. 다형성(polymorphism)
      1. 다형성이란?
        1. 객체지향개념에서 다형성이란 '여러가지 형태를 가질 수 있는 능력'을 의미한다. 구체적으로 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하였다. 자바에서는 한 타입의 참조변수를 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 구현하였다.
        2. GreekYogurt클래스와  FruitYogurt클래스가 서로 상속관계에 있을 경우, 부모클래스 타입의 참조변수 g가 자식클래스의 인스턴스를 참조할 수 있다. 하지만 참조변수 g로 FruitYogurt의 모든 멤버를 사용할 수 없다. g와 y모두 같은 타입의 인스턴스이지만 g는 FruitYogurt의 멤버변수 중 GreekYogurt의 멤버변수와 GreekYogurt로부터 상속받은 멤버들만 사용할 수 있다. y의 apple, strawberry, grapes, mix()는 사용할 수 없다. 둘 다 같은 타입의 인스턴스일지라도 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.
        3. class GreekYogurt{
          	int milk; 
              int lemon;
              String taste;
              
              void make(){ ... }
              void sell(){ ... }
          }
          
          class FruitYogurt extends GreekYogurt{
          	int apple;
              int strawberry;
              int grapes;
              
              void mix(){...}
          }
          
          GreekYogurt g = new GreekYogurt();
          FruitYogurt y = new FruitYogurt();
          GreekYogurt g = new FruitYogurt();


      2. 참조변수의 형변환
        1. 기본형 변수처럼 참조변수도 형변환이 가능하다. 서로 상속관계에 있는 클래스 사이에서만 가능하기 때문에 자식타입의 참조변수를 부모타입의 참조변수로, 조상타입의 참조변수를 자손타입의 참조변수로의 형변환만 가능하다. 기본형 변수의 형변환에서 작은 자료형에서 큰 자료형의 형변환은 생략이 가능했던 것처럼 참조변수의 형변환에서도 자식타입의 참조변수를 부모타입으로 형변환하는 경우에는 형변환을 생략할 수 있다.
        2. 형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는게 아니므로 참조변수의 형변환은 인스턴스에 아무런 영향을 미치지 않는다. 단지 참조변수의 형변환을 통해서 참조하고있는 인스턴스에서 사용할 수 있는 멤버의 범위를 조절하는 것 뿐이다.
        3. 서로 상속관계에 있는 타입간의 형변환은 양방향으로 자유롭게 수행될 수 있으나, 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 허용되지 않는다. 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요하다.
      3. instanceo연산자
        1. 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 instanceof연산자를 사용한다. 어떤 타입에 대해 instanceof연산의 결과가 true라는 것은 검사한 타입으로 형변환이 가능하다는 것을 의미한다.
      4. 참조변수와 인스턴스의 연결
        1. 부모클래스에 선언된 멤버변수와 같은 이름의 인스턴스 변수를 자식 클래스에 중복으로 정의했을 때, 부모타입의 참조변수로 자식 인스턴스를 참조하는 경우와 자식타입의 참조변수로 자식 인스턴스를 참조하는 경우는 서로 다른 결과를 얻는다. 메서드의 경우 부모 클래스의 메서드를 자식 클래스에서 오버라이딩 한 경우에도 참조변수의 타입에 관계없이 항상 실제 인스턴스의 메서드가 호출되지만, 멤버변수의 경우 참조변수의 타입에 따라 달라진다.
        2. 자식 클래스에서 부모 클래스의 멤버를 중복으로 정의하지 않았을 때는 참조변수의 타입에 따른 변화가 없다. 부모클래스의 멤버가 호출되어야 할지, 자식클래스의 멤버가 호출되어야 할 지 선택의 여지가 없기 때문이다. 참조변수의 타입에 따라 결과가 달라지는 경우는 부모클래스의 멤버변수와 같은 이름의 멤버변수를 자식 클래스에 중복해서 정의한 경우이다.
      5. 매개변수의 다형성
        1. PrintStream클래스에 정의되어 있는 print(Object obj)메서드는  매개변수로 Object 타입의 변수가 선언되어 있는데 Object 클래스는 모든 클래스의 조상이므로 이 메서드의 매개변수로 어떤 타입의 인스턴스든 다 올 수 있다. 이 하나의 메서드로 모든 타입의 인스턴스를 처리할 수 있다.
      6. 여러 종류의 객체를 배열로 다루기
        1. 조상타입의 참조변수 배열을 사용하면 공통의 조상을 가진 서로 다른 종류의 객체를 배열로 묶어서 다룰 수 있다. 묶어서 다루고싶은 객체들의 상속관계를 따져서 가장 가까운 공통조상 클래스 타입의 참조변수 배열을 생성해서 객체를 저장하면 된다.
        2. Vector클래스를 사용하면 내부적으로 Object타입의 배열을 가지고 있어서 이 배열에 객체를 추가하거나 제거할 수 있도록 작성되어 있다. 배열의 크기도 알아서 관리해주기 때문에 저장할 인스턴스의 개수를 신경쓰지 않아도 된다.
Designed by Tistory.