생성자, OOP, 추상클래스, 오버라이딩

calis_ws·2023년 5월 9일
0

역 피라미드

  • 4주차 2일 수업로그
public class PyramidReverse {		// repeat 함수와 메소드를 이용했다.
    public PyramidReverse(String spaceChar) {
        this.spaceChar = spaceChar;
    }
    private String spaceChar = "0";
    public void printPyramid(int height) {
        for (int i = height; i >= 0; i--) {
            System.out.printf("%s%s\n", spaceChar.repeat(height - i), "*".repeat(2 * i + 1));
        }
    }
    public String makeALine(int h, int i) {
        return String.format("%s%s\n", spaceChar.repeat(h - i), "*".repeat(2 * i + 1));
    }
    public static void main(String[] args) {
        PyramidReverse pyramid2 = new PyramidReverse(" ");
        PyramidReverse pyramidSpacezero = new PyramidReverse("0");
        pyramid2.printPyramid(4);
        pyramid2.printPyramid(5);
    }
}

생성자

  • Class와 이름이 같은 메소드
  • new를 할 때 실행 됨
  • 매개변수로 값을 받을 수 있다.

생성자는 왜쓰나요?

  • 멤버변수를 바꿔주기 위해 쓴다.
  • 소스코드를 수정하지 않고 클래스에 변화를 주기 위해

Constructor(생성자) 단축키

Alt + Insert

생성자 붙이기

생성자를 붙여야 켜고 끌 수(변경 가능) 있습니다.

public class ReversePyramid {
   private String spaceChar = "0";	// 멤버변수 선언 기본적으로 private을 쓴다.
   
   public ReversePyramid(String spaceChar) {	// 생성자
       this.spaceChar = spaceChar;
   }
// 중략

OOP로 나아가는 과정

  • main( )을 만든다.
  • 핵심 로직을 만든다.
  • 메소드로 분리 한다.

메소드 분리, 생성자 추가 하는 시점

  • 설계를 잘하면 좋지만 설계를 완벽하게 하는 것은 불가능
  • 요구사항이 나오면 그때 리팩토링 한다.
  • '복붙'(Ctrl + c + Ctrl v)은 고려하지 않음
    Ex)

리팩토링

반복하는 로직 + 핵심 로직 + 출력하는 로직 → Coupling

영역이 다르다!!

main 메소드는 Static 영역 : ~Test 클래스를 만든다고 생각
이외에는 Heap 영역

public class Pyramid3 {
 	   // 나머지는 모두 여기에서
   private int height = 4;
		
   public void printSth() {
       for (int i = 0; i < height; i++) {
           System.out.println(i);
       }
   }
  
   public static void main(String[] args) {
       // main은 new, 메소드 호출
       Pyramid3 pyramid3 = new Pyramid3();
       pyramid3.printSth();
   }
}

Util 클래스로 만들어서 전역에서 호출해서 사용

Spring 에서 Object 만들 때 자주 사용한다.

public class PrintStarUtils {
   public static String makePyramidLine(int height, int i) {
       return String.format("%s%s\n", " ".repeat(height - i - 1), "*".repeat(2 * i + 1));
   }
}

다른 클래스에서 new 없이 호출이 가능하다.

public class CallStaticMethod {
   public static void main(String[] args) {
       int h = 4;
       for (int i = 0; i < h; i++) {
           String line = PrintStarUtils.makePyramidLine(h, i);
           System.out.print(line);

생성자 오버로딩

오버로딩(Over Loading)이란?
파라메터가 다른 같은 이름의 메소드를 추가로 만드는 것

plus();							→ 같은 이름 다른 파라메터 ()없음
plus(int val);					→ 같은 이름 다른 파라메터 (int val) 1plus(int val1, int val2);		→ 같은 이름 다른 파라메터 (int val1, int val2) 2

왜 쓰는지?

  • 기본값 세팅을 다르게 하기 위해
  • 타입이 다른 경우
  • 일부 값만 세팅하기 위해

this

this는 클래스를 가리킨다.
변수의 이름이 같을 때 구분 해주기 위해 쓴다.

private int[][] arr;

   public Codeup1098_OOP(int[][] arr) {
       this.arr = arr;				// arr = arr; 작동 안됨
   }
   
	public Codeup1098_OOP(int[][] arr2) {
	   arr = arr2;					// this 없이도 가능한 경우
	}

Abstract Class(추상 클래스)

  • 1개 이상 추상 메소드를 포함하는 클래스
  • 반드시 구현해서 사용 해야한다.
  • 남은 부분을 활용하기 위함
  • Template Method Pattern
public abstract class ShapeDrawer {			// Abstract Class
  
  	public void printShape(int height) {	// printShape은 공통으로 쓸 수 있다.

       for (int i = 0; i < height; i++) {
           System.out.print(makeALine(height, i));
       }
   }
   public abstract String makeALine(int h, int i);
										// Abstract Method
}

부모 Class : ShapeDrawer
자식 Class : PyramidShapeDrawer

추상 메소드 오버라이딩(Method Overriding)

  • 오버라이딩이란 메소드를 재 정의 하는 것
  • 추상클래스는 재정의는 아니고 구현 하는 것

자바에서 '전달(Injection)'

DI(Dependency Injection) → 의존성 주입
DiEx 라는 클래스에서 ShapeDrawer를 사용(의존 Depends)한다.
객체 간의 '결합도를 낮추기 위해' 사용된다.

A 객체가 B 객체에 의존한다 - 출처 백엔드 위키 5팀 '오'로나민 C

  • A 객체에서 B 객체를 직접 생성하거나 참조
    • B 객체를 수정하거나 대체해야 할 경우에 A 객체를 수정
  • A 객체가 B 객체를 주입
    • B 객체를 수정하거나 대체해도 A 객체를 수정하지 않아도 된다.
public class DiEx {  /* DiEx 클래스는 ShapeDrawer 클래스의 인스턴스를 생성하지 않고, 
				        생성자를 통해 ShapeDrawer 인스턴스를 주입받는다. */ 
    private ShapeDrawer shapeDrawer;
    public DiEx(ShapeDrawer shapeDrawer) {
        this.shapeDrawer = shapeDrawer;
    }

    public void doSth() {
        shapeDrawer.printShape(5);

    }
}
class DiExTest {
    public static void main(String[] args) {
        ParallelogramShapeDrawer psd = new ParallelogramShapeDrawer();
        DiEx diEx = new DiEx(psd);	// Q. 어떻게 Parrelogram을 호출 했지?
        diEx.doSth();				// A. Parrelogram이 ShapeDrawer의 자식이니까
    }
}
  • 의존성을 주입하지 않은 경우
public class DiEx {
   private ShapeDrawer shapeDrawer = new ShapeDrawer();

   public void doSth() {
       shapeDrawer.printShape(5);
   }
}

스타크래프트 유닛을 추상클래스로

abstract class Unit()				// → 유닛이라는 추상 클래스

class Marin extends Unit{}			// 마린을 상속
class Firebat extends Unit{}		// 파이어뱃을 상속

라면을 추상클래스로

public abstract class JinRamen{ 	// → 라면이라는 추상 클래스
    public String noodle() {
    }
    public abstract String soup();
}

public class JinRamenHot extends JinRamen{ 		// 진매
    @Override
    public abstract String soup() {
      sout(”매운맛 입니다");
    }
}
 
public class JinRamenMild extends JinRamen{ 	// 진순
    @Override
    public abstract String soup() {
      sout(”순한맛 입니다");
    }
} 

인사이트 타임

Abstract Class(추상 클래스)

  • 원기님의 설명

DI(의존성 주입)

public class DiEx { 
    private ShapeDrawer shapeDrawer;
    public DiEx(ShapeDrawer shapeDrawer) {
        this.shapeDrawer = shapeDrawer;
    }

    public DiEx(ParallelogramShapeDrawer parallelogramShapeDrawer) {
        this.parallelogramShapeDrawer = parallelogramShapeDrawer;
    }
    private ParallelogramShapeDrawer parallelogramShapeDrawer;

    public void doSth() {
        shapeDrawer.printShape(5);
        parallelogramShapeDrawer.printShape(5);
    }
}
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.example.javaproject2.week4.day2.ShapeDrawer.printShape(int)" because "this.shapeDrawer" is null
    at com.example.javaproject2.week4.day2.DiEx.doSth(DiEx.java:14)
    at com.example.javaproject2.week4.day2.DiExTest.main(DiExTest.java:8)
  • 태환님과 원기님의 피드백으로 에러 해결 완료

도와주신 두 분께 감사의 말씀을 전한다.

Ctrl + B : 모든 상속 관계 확인 가능

Ctrl + Alt + Shift + U : UML 클래스 다이어그램
(커뮤니티 버전은 사용 불가)

Review

오늘은 OOP에 대해 제대로 파헤치기 시작했다. 생성자부터 추상클래스를 지나 의존성 주입까지 정말 많은 것들을 배운 시간이었다.

메소드를 시작한지 이틀 째라 익숙하지 않은 상태임에도 불구하고 강사님의 후진없는 진도는 나의 뉴런들을 파괴시키고야 말았다.

하지만 역시나 어려운 내용임에도 불구하고 갓사이트 타임을 활용해 팀원들과의 소통으로 많은 것들을 배웠다. 두시간도 안되는 시간이지만 역시 효과는 최고인 것 같다.

앞으로 Spring을 이용한 개발을 하기 위해선 OOP에 대해 빠삭해야 한다는 것쯤은 알고 있다. 시간이 좀 걸리겠지만 포기만 하지 말자 오늘도 해냈으니까.
내일도 파이팅

profile
반갑습니다람지

0개의 댓글