KOSTA 7일차) 싱글톤 / getter setter / 접근제어자

해버니·2023년 2월 25일
0

KOSTA

목록 보기
12/32
post-thumbnail

💜접근 제어자💜

클래스, 메서드, 멤버변수들을 어디까지 접근할 수 있도록 허용할 것인지 결정
클래스 : default, public
메서드/멤버변수 : private, default, public, protected



❓ 접근 제어자 왜 써 ❓
데이터를 어디까지 읽고 쓸 수 있는지 정해서
데이터를 보호하기 위함 : 무결성을 보장하기 위해
(무결성 : 데이터의 정확성일관성을 유지하고 보증하는 것을 말함)

예를 들어, 나이, 책 페이지, 자동차의 속도 등은 음수가 될 수 없다.
만약 외부에서 해당 데이터를 음수로 변경하게 될 경우 객체의 무결성이 깨진다.






✨생성자를 비롯한 대부분 메서드는 public이다.
그래야 다른 패키지에서도 호출이 가능하기 때문이다.










class PrivateTest{
   private int a;
   int b;
   public int c;
}

① private

☆은닉성☆ 제공 → 클래스 안에서만 보인다.

class PrivateTest{
   private int a;
}





② default

키워드 없음. 현재 패키지 내에서만 보인다.
다른 클래스에서도 사용이 가능하지만 같은 패키지에 있는 클래스에서만 보인다.

class PrivateTest{
   int b;
}





③ public

현재 패키지, 다른 패키지 모두 보인다.
다른 패키지에서는 상속관계의 클래스에만 보임

class PrivateTest{
   public int c;
}





④ protected









✨ 예제 ✨


AccesTest.java

package prj2_3;

// public 클래스
public class AccessTest {
	private int a; // private 멤버
	int b; // default 멤버
	public int c; // public 멤버

	// 생성자를 비롯한 대부분 메서드는 public
	public AccessTest(int a, int b, int c) {
		this.a = a;
		this.b = b;
		this.c = c;
	}

	public void printData() {
		System.out.println("a : " + a);
		System.out.println("b : " + b);
		System.out.println("c : " + c);
	}
}

// default 클래스
class MyTest {
	int x;
	int y;
}


위에서

public class AccessTest{
	private int a;
    int b;
    public int c;
}

class MyTest{
	int x;
    int y;
}

으로 선언했다.






AccessTestMain.java

package prj2_3;

public class AccessTestMain {

	public static void main(String[] args) {
		AccessTest at = new AccessTest(1, 2, 3);

		// private 멤버는 다른 클래스에서 사용 불가
		// System.out.println(at.a);
		System.out.println(at.b);
		System.out.println(at.c);
		at.printData();

		MyTest mt = new MyTest();
		mt.x = 10;
		mt.y = 20;

	}

}

a는 private로 선언했다.
private는 다른 패키지에서 사용이 불가능 하므로

System.out.println(at.a)

위는 쓰지 못한다. 🚨에러 발생🚨
default로 설정한 b와 public으로 설정한 c만 사용이 가능하다.

그리고 클래스 MyTest는 default 클래스이다.
default 클래스는 같은 패키지 안에서 사용이 가능하고 다른 패키지에서는 읽을 수 없다.
위는 같은 패키지에 위치하기 때문에 선언이 가능하다.





AccessTestMain.java

package Task_0221;

import prj2_3.AccessTest;

public class AccessTestMain {

	public static void main(String[] args) {

		// public 클래스는 다른 패키지에서 객체 생성 가능
		AccessTest at = new AccessTest(1, 2, 3);

		// System.out.println(at.a);	private 멤버는 다른 클래스에서 사용 불가
		// System.out.println(at.b);	default는 다른 패키지에서 안 보임
		System.out.println(at.c);		//public은 다른 패키지에서도 보임
		at.printData();					// public 메서드이므로 호출 가능

		// default 클래스는 다른 패키지에서 안 보임. 객체 생성 불가능
		// MyTest mt = new MyTest();
		
		// mt.x = 10;
		// mt.y = 20;
	}
}

위 소스는 다른 패키지에서 만든 파일이다.
private는 다른 클래스에서 사용이 불가능 하므로 에러가 발생하고,
default로 선언한 b는 다른 패키지에서는 보이지 않기 때문에 에러가 발생하게 된다.







getter & setter

(단축키 : Alt + Shift + S → R)

객체 지향 프로그래밍에서는 메서드를 통해 데이터를 변경하는 방법을 선호한다.
getter와 setter은 보통 세트로 많이 사용하지만 경우에 따라서는 필요한 메소드만 생성할 수도 있다.

VO를 만들 때는 getter, setter를 무조건 넣어줘야 한다.
toString은 없어도 무방하지만 있으면 편하다.






① setter

private 멤버에 값 할당 public 메서드
외부에서 데이터에 접근하지 못하게 막고 외부에서 메소드를 통해 데이터에 접근하도록 유도하는 것.
주로 데이터를 변경하는 역할을 한다.

public void set멤버변수명(멤버변수와 동일한 타입 변수){
	this.a = a;
}

단, 무분별한 Setter는 데이터 무결성을 해칠 수 있다.
이를 해결하기 위해서 객체를 생성하는 생성자와 이를 표현하는 메소드를 분리하여 사용하는 Builder 패턴을 이용할 수 있다.




② getter

private 멤버의 값을 반환 public 메서드
객체 외부에서 객체 필드값을 사용하기 부적절한 경우가 있다.
이런 경우 메소드로 필드값을 가공 후, 외부로 전달하는 것. (정의)
주로 데이터를 읽어오는 역할을 한다.

public 멤버와같은타입 get멤버변수명(){
	return 맴버변수값;
}









🤍싱글톤🤍

하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴

생성자를 private으로하여 클래스 밖에서 객체 생성 불가
내부에서 객체를 생성해야 하고 이 객체를 static 멤버 변수에 저장
static 변수에 저장한 이유는 하나를 공용으로 사용하기 위해서.
→ 객체를 오직 하나만 생성하여 생성된 객체를 프로그램
어디에서나 접근하여 사용할 수 있도록 하는 패턴.
이 객체를 외부에 전달할 public static SingleTone getInstance() 메서드를 제공해야한다.


package prj2_3;

class SingleTone{
	int a;
	private SingleTone() {}
	// 이렇게 하면 객체 생성이 가능할까? 안 된다.
}

public class SingleToneTest {
	public static void main(String[] args) {
		SingleTone s=new SingleTone(); // 빨간줄 뜸
	}
}






그러면 이 싱글톤을 어떻게 활용할까?

class SingleTone{
	// 만든 객체는 static 변수에 담는다. 하나의 객체를 공용으로 사용
	// 객체 개수를 못 늘리게 하기 위해서 사용하는 것

	private static SingleTone s=new SingleTone();
	private int a;

	// 객체를 외부에서 생성하지 못하게 함
	private SingleTone() {
	}
	// 내부에서 만든 객체를 반환
	public static SingleTone getInstance() {
		return s;
	}
	
	public int getA() {
		return a;
	}
	public void setA(int a) {
		this.a = a;
	}
}

public class SingleToneTest {
	public static void main(String[] args) {
		SingleTone s=SingleTone.getInstance();
		s.setA(50);
		System.out.println(s.getA());				
	}
}

기본적으로 이렇게 쓴다.




SingleTone s=SingleTone.getInstance();

new를 쓰지 않고 보통 getInstance()의 이름을 가진 것으로
사용한다.




❓ 싱글톤을 사용하는 이유 ❓

① 자원 관리 : 메모리 측면
최초 한 번의 new 연산자를 통해서 고정된 메모리 영역을
사용하기 때문에 추후 해당 객체에 접근할 때 메모리 낭비를
방지할 수 있다.

② 데이터 공유가 쉽다.

싱글톤 인스턴스가 전역으로 사용되는 인스턴스이기 때문에
다른 클래스의 인스턴스들이 접근하여 사용할 수 있다.












참고
https://thalals.tistory.com/279

0개의 댓글