Day 19 (23.01.19)

Jane·2023년 1월 19일
0

IT 수업 정리

목록 보기
19/124

1. 정보 은닉

  • 데이터를 변수에 직접 접근할 수 없도록 한다. (직접 접근하면 문제가 일어날 수 있기 때문이다.) >> private
    함수를 통해서만 값을 설정할 수 있도록 한다.
  • 직접 접근을 방지하기 위해 문법을 만들어서 (접근 제어) 컴파일 에러를 일으키도록 한다.

1-1. 데이터 접근에 대한 예제 코드

class Circle {
//	double rad = 0;
	private double rad = 0; // 반지름 설정
	final double PI = 3.14; // PI

	public Circle(double r) { // 생성자 함수
		setRad(r);
	}

	public void setRad(double r) { // 반지름을 설정하는 함수
		if (r < 0) {
			rad = 0;
			return;
		}
		rad = r;
	}
	
	public double getArea() { // 넓이를 구하는 함수
		return (rad * rad) * PI;
	}

}

public class JavaPractice {

	public static void main(String[] args) {
		Circle c = new Circle(1.5);
		System.out.println(c.getArea());
		
		c.setRad(2.5);
		System.out.println(c.getArea());
		c.setRad(-3.3);
		System.out.println(c.getArea());
		
	//	c.rad = -4.5;
	//	System.out.println(c.getArea());
	}

}
  • c.rad = -4.5; 처럼 직접 접근하게 되면
    생성자 함수(와 setRad() 함수)를 거치지 않게 되고
    getArea() 함수를 실행하게 되면서, 63.585 를 출력하게 된다.
    (0보다 작은지 확인도 안하고 제멋대로 들어와서 계산해버림)
  • 이처럼 직접 접근하는 것을 막기 위하여 rad에 private 접근자를 붙인다.
  • 인스턴스 변수인 rad를 긁어서 Source > Generate Getters and Setters를 확인해보면 getPI, getRad, setRad 등을 확인할 수 있다.

  • c.rad 는 Setter인 setRad() 함수 형식으로 바꾸게 되면 더이상 Error가 표시되지 않는다.

1-2. 접근 제어자 (access modifier)

  • 접근 제한자? 접근 수준 지시자? ...
  • 접근을 제한할 수 있다.
  • 함수에도, 변수에도, 클래스에도 붙일 수 있다.
  • 종류
    • private : 같은 클래스 안에서만 접근이 가능하다.
    • default : 같은 패키지 안에서만 접근이 가능하다.
      (아무 것도 붙이지 않으면 default.)
    • protected : 같은 패키지 안에서 접근 + 다른 패키지의 자손 클래스(상속받은 클래스)에 접근이 가능하다.
    • public : 접근 제한을 두지 않는다.

1-3. 접근 제어 연습

example1 패키지 - A.java

package example1;

public class A {
	int a; // default
//	public int a;	
	
    public A(){}
    
	private void accessTest() {
		
	}
// void accessTest() {}
}

example2 패키지 - B.java

package example2;

import example1.A;

public class B {
	int b;
	
	void accessTest() {
		A a = new A();
        a.accessTest();
        // 다른 패키지이므로 접근 불가
		System.out.println(a.a);
		// public 붙이면 Error 없음, public 떼면 default로 변경되므로 Error
	}
}

example1 패키지 - C.java

package example1;

public class C {
	int c;
	
	void accessTest() {
		A a = new A();
        a.accessTest();
        // 같은 패키지에 있어도 다른 클래스에 있으므로 private에는 접근 불가
		System.out.println(a.a);
		// 같은 패키지는 default에 접근 가능하다
	}
	
}
  • default의 범위 : 같은 패키지 안에서만 접근 가능, 다른 패키지에서는 접근 불가 (오류)
    • System.out.println(a.a); 접근 가능? (클래스 안의 인스턴스에 default, public, private 지정해보기)
    • a.accessTest(); 접근 가능? (함수에 default, public 지정해보기)
    • 생성자 함수를 직접 만들어준 경우에도 default가 붙는다. >> 다른 패키지에도 Error 날 수도 있다. (A()에 default, public 지정해보기)
    • 클래스에도 default를 주면 다른 패키지에서 import할 때 오류 발생! public 지정해줘야 다른 패키지에서 import 할 때 오류가 나지 않는 것을 확인할 수 있다. (class 앞에 default, public 지정해보기)

2. 정보 은닉을 적용한 예제

2-1. Baby 클래스

class Baby {
	private int age;
	private String name;
	
	public void initBaby(int a, String b) {
		age = a;
		name = b;
	}
	
	public void show() {
		System.out.println(age + "살 " + name + "입니다");
	}
	
	public void setAge(int num) { // 나이를 설정하는 함수
		if (num < 0) {
			num = 0;
		}
		age = num;
	}
	
	public int getAge() { // 나이를 리턴하는 함수
		return age;
	}
}

class ObjectTest {

	public static void main(String[] args) {

		Baby baby = new Baby();
		baby.initBaby(5,"아기");
		baby.show();
	}

}

2-2. Rectangle 클래스

  • rec.width, rec.height : 컴파일 에러 (private인데 직접적으로 접근을 시도한다)
  • new Rectangle으로 객체를 생성할 때, 매개변수의 값이 음수이면 잘못된 입력으로 리턴하도록 한다.
class Rectangle {
	private int width;
	private int height;

	// data는 private, method()는 public

	public Rectangle(int width, int height) {
		setWidth(width);
		setHeight(height);
	}

	public void setWidth(int width) {
		if (width < 0) {
			this.width = 0;
			System.out.println("잘못된 입력입니다.");
			return;
		}
		this.width = width;
	}

	public void setHeight(int height) {
		if (height < 0) {
			this.height = 0;
			System.out.println("잘못된 입력입니다.");
			return;
		}
		this.height = height;
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	void show() {
	}

	int getArea() {
		return width * height;
	}
}

class ObjectTest {

	public static void main(String[] args) {

		Rectangle rec = new Rectangle(10, -20);
//		rec.width = 10;

	}

}

3. 정보 은닉 심화 예제 (Rectangle 클래스)

class Rectangle {
	private int x;
	private int y;
	private int width;
	private int height;

	// data는 private, method()는 public

	public Rectangle(int x, int y, int width, int height) {
		// x, y는 좌표, width는 가로, height는 세로
		setX(x);
		setY(y);
		setWidth(width);
		setHeight(height);
	}

	public int getX() { // x좌표 얻어오기
		return x;
	}

	public void setX(int x) { // x좌표 설정
		this.x = x;
	}

	public int getY() { // y좌표 얻어오기
		return y;
	}

	public void setY(int y) { // y좌표 설정
		this.y = y;
	}

	public void setWidth(int width) { // 가로 길이 설정하는 함수
		if (width < 0) {
			this.width = 0;
			System.out.println("잘못된 입력입니다.");
			return;
		}
		this.width = width;
	}

	public void setHeight(int height) { // 세로 길이 설정하는 함수
		if (height < 0) {
			this.height = 0;
			System.out.println("잘못된 입력입니다.");
			return;
		}
		this.height = height;
	}

	public int getWidth() { // 가로 길이 리턴
		return width;
	}

	public int getHeight() { // 세로 길이 리턴
		return height;
	}

	public int square() { // 사각형 넓이 리턴
		return width * height;
	}

	public void show() { // 사각형의 좌표와 넓이 출력
		System.out.println("(" + x + "," + y + ")에서 크기가 " + width + "x" + height + "인 사각형");
	}

	public boolean contains(Rectangle rectangle) {
		/*
		 	나의 x좌표가 매개변수의 x좌표보다 작거나 같다
         && 나의 (x+width)좌표가 매개변수의 (x+width)좌표보다 크거나 같다
         && 나의 y좌표가 매개변수의 y좌표보다 작거나 같다
         && 나의 (y+height)좌표가 매개변수의 (y+height)좌표보다 크거나 같다
		 */

		if ((this.x <= rectangle.x) && ((this.x) + (this.width) >= (rectangle.x) + (rectangle.width))
				&& (this.y <= rectangle.y) && (this.y) + (this.height) >= (rectangle.y) + (rectangle.height)) {
			return true;
		} else {
			return false;
		}
	}

}

class ObjectTest {

	public static void main(String[] args) {
		Rectangle r = new Rectangle(2, 2, 8, 7);
		Rectangle s = new Rectangle(5, 5, 6, 6);
		Rectangle t = new Rectangle(1, 1, 10, 10);
		Rectangle w = new Rectangle(3, 7, 2, 8);

		r.show();
		System.out.println("s의 면적은 " + s.square());

		if (t.contains(r)) {
			System.out.println("t는 r을 포함합니다.");
		}
		if (t.contains(s)) {
			System.out.println("t는 s를 포함합니다.");
		}
		if (t.contains(w)) {
			System.out.println("t는 w를 포함합니다.");
		}

	}

}

[Console]
(2,2)에서 크기가 8x7인 사각형
s의 면적은 48
t는 r을 포함합니다.
t는 s를 포함합니다.

boolean contains(Rectangle) 함수 다른 코드

public boolean contains(Rectangle rectangle) {
	boolean flag = true;
	if (this.x > rectangle.x) {
		flag = false;
	}
	if (this.y > rectangle.y) {
		flag = false;
	}
	if ((this.x) + (this.width) < (rectangle.x) + (rectangle.width)) {
		flag = false;
	}
	if ((this.y) + (this.height) < (rectangle.y) + (rectangle.height)) {
		flag = false;
	}
	return flag;
}
 public boolean contains(Rectangle r) {
     if(x < r.x && y < r.y) {
           if((width+x) > (r.x + r.width) && (height + y) > (r.y + r.height)) {
              return true;
           }
     }
      
     return false;
  }
profile
velog, GitHub, Notion 등에 작업물을 정리하고 있습니다.

0개의 댓글