[JAVA] Day 12 - 변수 / 형변환 / Singleton / 상속 / Overriding / Final / Abstract 추상메서드

sue·2023년 11월 29일

📒국비학원 [JAVA]

목록 보기
9/20
post-thumbnail

변수(Variable)란?

메모리에 할당된 공간 (데이터를 담는 공간) ← 이 공간에 데이터가 저장됨
변수를 이용해서 데이터를 읽고 쓰고 조작 가능

  • 인스턴스 변수 (Instance Variable) :
    클래스 내에서 선언, 각 객체(instance)마다 있는 변수
    객체생성 [new] 될 때마다 새로운 메모리 공간 할당
    ③ 클래스 내 메서드에서 this로 접근 가능
    ex) class Abce {
    int a; //instance 변수
    }
    this.a = 20; //instance 변수에 접근

  • 전역변수 (Global Variable) :
    클래스 밖에서 선언, 프로그램 전체에 사용되는 변수
    ② 프로그램이 시작될 때 메모리에 할당 (객체생성과 관계 X)
    클래스 안에서는 static 변수로 선언

    static 변수(전역변수) :
    static이 붙은건 = 클래스 멤버, 해당하는 클래스의 객체를 생성하지 않고도 접근가능
    ex) class Abce {
    static int b; //전역변수
    }
    b = 20; //전역변수에 접근

  • 로컬변수 (Local Variable):
    메서드 내에서만 사용
    ② 해당 메서드가 실행될 때마다 메모리 할당 -> 메서드 종료 후 소멸

형변환

  • 자식 → 부모 UpCasting
  • 부모 → 자식 DownCasting
  • ex, ((Test)ob).x : ob를 Test로 형변환하고, Test안에 있는 x값 출력
    예외 ) 무조건 메서드는 자식껏만 쓴다 (Test.1 참고)

싱글톤 (Singleton) :

  • 객체를 계속해서 생성해내는 것이 아니라 하나의 객체만 생성해서 공유하는 사용법
  • ex) Calendar now = new getInstance( );
    여기서 new getInstance( ) => static (처음 만들 때 메모리 할당 한번만! 하고 공유해서 사용)
  • 또 다른 말로는, 클래스가 한번만 메모리 할당하고 (static), 그 메모리에 전역변수를 사용하지 않고 인스턴스 하나를 만들어 객체를 하나만 생성하여 공유하는 법
  • 설정값 / 동일한 리소스에 대한 동시접근을 제어하기 위해 사용
  • 장점 : 전역변수 많이 쓰는 것과 메모리 낭비를 줄일 수 있음

추상클래스 (Abstract) :

메모리 낭비 없이 class 미리 설계 (⑥ → 해당 클래스의 Instance가 메모리에 생성되지 X)
② 메서드를 재정의해서 사용함 (= 다형성)
추상클래스 안에는 반드시 한개 이상의 추상 메서드가 있어야 함 (+ 일반적인 메서드들도 입력할 수 있음)
④ 추상 클래스를 상속받으면 무조건 자식이 Override 해야 함
(단, final 붙은건 안됨)

⑤ 추상 메서드(Abstract Method) :
추상 클래스 내에 있지만, 구현되지 않음
-> 추상 메서드는 반드시 상속받는 자식메서드에서 구현되어있어야 함
⑥ 추상 클래스는 직접 객체 생성 X (상속받는 자식 클래스에서 객체 생성 O)
⑦ ⑥번에 이어 상속받는 자식 클래스에서 객체를 생성하므로 출력은 [ 자식 클래스.공통된 메서드( ); ]가 됨


🔎 [Eclipse] - [package] - [class] 생성


📌 Note Code


  • 암시적 형변환 : 큰값 ← 작은값
  • Override [오버라이드] : 상속관계에서 부모에 이미 있는 메서드를 자식에서 같은 메서드이름(매개변수)로 다시 정의하는 것
  • 메서드에서 public void print() -> write( ) 메서드 호출 가능
  • 상속관계일 때, 자식 class안에서 자식께 있지만, 부모꺼 호출 가능 super.변수
  • 자식의 대명사 : this , 부모의 대명사: super
  • object 기본생성자 -> 메모리상 올려
    Test 기본생성자안에서 super찾고 -> 메모리상 올려
    Demo 기본생성자안에서 super찾고 -> 메모리상 올려
    -> 그럼 상속관계 성립



1. 메서드 / 오버라이드 / 형변환 개념 이해하기

Test1

💻 입력

class Test {

	protected int a = 10, b = 20;

	public void write() {
		System.out.println("Super Class write()...."); // 부모=super
		System.out.println("a : " + a + ",b: " + b);

	}

}

class Demo extends Test {

	protected int b = 30, c = 40;

	@Override
	public void write() {
		System.out.println("Sub Class write()...");
		System.out.println("a : " + a + ", b: " + b + ", c: " + c);
		//상속으로 인해 부모 a 가져다 씀
		// 부모도 있고 자식도 둘 다 b를 가지고있으면 자식 b출력

		System.out.println("super.b: " + super.b); // 해당 class안에서만 가능

	}

	public void print1() {
		System.out.println("Sub Class print1()...");
		
		
		write();// 부모도 있고 자식도 둘 다 write( ) 가지고있으면 자식 wirte 출력

	}

	public void print2() {
		System.out.println("Sub Class print1()...");
		super.write(); // super - 부모꺼
	}

}

public class Test1 {

	public static void main(String[] args) {

		Demo ob = new Demo(); // 기본생성자 안에서 super 찾고, 메모리 올리는 일을 반복 후 상속관계 성립
	
		ob.write();
		System.out.println("---------------------");
		ob.print1();
		System.out.println("---------------------");
		ob.print2();

		System.out.println("---------------------");
		System.out.println("ob.b: " + ob.b);

		//
		System.out.println("((Test)ob).b: " + ((Test) ob).b); //(부모로 형변환)자식.b = 부모의 b
		
		//자식의 write - 부모꺼를 오버라이딩해서 자식이 둘다 가지고있으면 자식의 의도가 들어갔기때문에
		//메서드 만큼은 무조건 자식꺼 씀
		((Test)ob).write(); 

	}

}

/*
int a; double b;

a = 10;

b = a; --->OK / 큰값 <- 작은값 들어감 / 암시적 형변환 
b = (double)a; --->OK : 강제 형변환

a = b; ---> X
a = (int)b --->OK : 강제 형변환


Demo a; 자식
Test b; 부모
 

* class = 자료형
Test(부모) = Demo(자식) --> OK  /          자식 -> 부모    UPCAST
Test(부모) = (Test)Demo(자식) --> OK   /   부모 -> 자식  DOWNCAST   :   형변환하면 가능
 
Demo(자식) = Test(부모) ---> X
Demo(자식) = (Demo)Test(부모) ---> OK
 */

💡 **출력**
Sub Class write()...
a : 10, b: 30, c: 40
super.b: 20
---------------------
Sub Class print1()...
Sub Class write()...
a : 10, b: 30, c: 40
super.b: 20
---------------------
Sub Class print1()...
Super Class write()....
a : 10,b: 20
---------------------
ob.b: 30
((Test)ob).b: 20
Sub Class write()...
a : 10, b: 30, c: 40
super.b: 20



📌 Note Code


  • Singleton : [3개 다 같은 말 - 이해 잘되는 문장으로 이해하기]
    ① 객체를 계속해서 생성해내는 것이 아니라 하나의 객체만 생성해서 공유하는 사용법
    ② ex) Calendar now = new getInstance( );
    여기서 new getInstance( ) => static (처음 만들 때 메모리 할당 한번만! 하고 공유해서 사용)
    하나의 객체 생성 후 여러곳에서 getInstance 메서드를 통해 접근 가능 & 같은 주소 공유



2. Singleton 개념 이해하기

Test2

💻 입력

class Sing {

	 //1개의 클래스 - Instance 변수 1개 [private로 외부 접근 막음] 
	private static Sing ob; 
 
	//getInstance 메서드를 통해서만 접근 가능
	public static Sing getInstance() { 
   
	//Instance가 없을 땐 객체 생성
		if (ob == null) {
			ob = new Sing();
		}
        
	//Instance가 있으면 ob값 반환
		return ob;
	}

}

public class Test2 {

	public static void main(String[] args) {

		//하나의 객체 생성 후 여러곳에서 getInstance 메서드를 통해 접근 가능 & 같은 주소 공유
		//static
		Sing ob1 = Sing.getInstance(); //Sing ob1 = Sing.ob(); : 10번지
		Sing ob2 = Sing.getInstance();

		if (ob1 == ob2) {
			System.out.println("동일한 객체!!");

		} else {

			System.out.println("동일하지 않은 객체!!");
		}

	}

}

💡 **출력**
동일한 객체!!


📌 Note Code


  • final : 상수변수
    Instance 변수 + final = 한번 초기화 한 후 변경 불가능
    Method + final = 자식이 Override(내용바꾸기) 불가능
    Class + final = 상속 불가능



3. final / 상속 / Override를 사용해서 원의 넓이를 구하여라

Test3

💻 입력

class TestB{
	
	public static final double PI; //double PI = 인스턴스변수 (한번 초기화한 후, 절대 바꿀 수 없음)
	//public static final double PI = 3.14; 
	
	static { // 얘만 static 주게 되면 위에껀 메모리에 안올라가서 같이 static써줘야함
		PI = 3.14;

	}

	public double area; // instance변수

	public final void write(String title) { 
		System.out.println(title + " : " + area);
	}

}


public class Test3 extends TestB {

	/*
	@Override
	public void write(String title) { //2. Method에 final을 붙이면 Override 불가능
		System.out.println("야호~~~");
	}
	*/
	
	public void circleArea(int r) {
		area = (double)(r*r*PI); //(double)r*r*PI = (double)r만 치환됨 , int * double = 암시적형변환 큰값으로 출력
		
	}
	
	
	public static void main(String[] args) {

		Test3 ob = new Test3();
		
		ob.circleArea(10);
		ob.write("원");
		
	}

}

💡 **출력**
원 : 314.0


📌 Note Code


  • 오버라이드

4. 추상클래스 (abstract) 개념 활용하기

Test4

💻 입력


abstract class ShapeClass{
	
	abstract void draw(); //추상메서드 - ;으로 끝남 , 오버라이드 할때 고정
	
}

class Circ extends ShapeClass{

	@Override //추상클래스 상속받으면 무조건 Override해야함
	public void draw() { //오버라이드 할때 고정
	System.out.println("원을 그린다");
	} 
	
}

class Rect extends ShapeClass{

	@Override 
	public void draw() {
		System.out.println("사각형을 그린다");
	}
	
}

class Tri extends ShapeClass{
	
	@Override
	public void draw() {
		System.out.println("삼각형을 그린다");
		
	}
	
}


public class Test4 {

	public static void main(String[] args) {

		Circ c = new Circ();
		Rect r = new Rect();
		Tri t = new Tri();
		
		c.draw();
		r.draw();
		t.draw();
	
	}

}

💡 **출력**
원을 그린다
사각형을 그린다
삼각형을 그린다


📌 Note Code


  • 추상클래스 내 메서드 = 메서드임에도 괄호 안함 / 그냥 세미콜론 ; 으로 끝냄 ex) protected abstract void sorting();



5. 메서드를 활용한 Selection Sort 정렬하기

Test5

💻 입력


abstract class SortInt{
	
	private int[] value;
	
	protected abstract void sorting(); //추상클래스 상속받으면 무조건 Override해야함
	
	// 우회도로
	public void sort(int[] value) { // 배열은 배열로 넘겨줘야함
 
		this.value = value;// 초기화 됨

		sorting();// 부모,자식 둘 다 가지고 있어도 메서드는 무조건 자식꺼 

	}

	
	// 배열의 개수 확인
	public int length() {

		if (value == null) {
			return 0; //0이면 false , 1이면 true반환
		}
		return value.length; // 배열에 쓰이는 length는 ()없음
	}

	protected final int compare(int i, int j) { 

		if (value[i] == value[j]) { //if쓰는 이유 확인용
			return 0;

		} else if (value[i] > value[j]) {
			return 1; //원하는 값

		} else {
			return -1;
		}

	}

	protected final void swap(int i, int j) { // 자리바꿈

		int temp;

		temp = value[i];
		value[i] = value[j];
		value[j] = temp;

	}

	public void print() {

		if (value == null) {
			return;
		}

		for (int su : value) { // (확장 for문) 알아서 배열의 개수만큼 실행해줌
			System.out.printf("%4d", su);
		}

	}

}

class SortTest extends SortInt { //자식이 부모꺼 상속받았으므로, final을 제외하곤 메서드로 만들 수 있음

	@Override
	protected void sorting() {

		// Selection Sort

		for (int i = 0; i < length() - 1; i++) {
			for (int j = i+1; j < length(); j++) {

				if (compare(i, j) > 0) { // 반환값 1이어야 함
					swap(i, j);
				}

			}
		}

	}

}

public class Test5 {

	public static void main(String[] args) {

		int[] data = {50,30,60,20,10}; 
		
		SortTest ob = new SortTest();
		
		ob.sort(data);
		ob.print();
		
		}

	}

💡 **출력**
  10  20  30  50  60

0개의 댓글