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를 할 때 실행 됨
- 매개변수로 값을 받을 수 있다.
- 멤버변수를 바꿔주기 위해 쓴다.
- 소스코드를 수정하지 않고 클래스에 변화를 주기 위해
Alt + Insert
생성자를 붙여야 켜고 끌 수(변경 가능) 있습니다.
public class ReversePyramid {
private String spaceChar = "0"; // 멤버변수 선언 기본적으로 private을 쓴다.
public ReversePyramid(String spaceChar) { // 생성자
this.spaceChar = spaceChar;
}
// 중략
- 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();
}
}
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) 1개
plus(int val1, int val2); → 같은 이름 다른 파라메터 (int val1, int val2) 2개
- 기본값 세팅을 다르게 하기 위해
- 타입이 다른 경우
- 일부 값만 세팅하기 위해
this는 클래스를 가리킨다.
변수의 이름이 같을 때 구분 해주기 위해 쓴다.
private int[][] arr;
public Codeup1098_OOP(int[][] arr) {
this.arr = arr; // arr = arr; 작동 안됨
}
public Codeup1098_OOP(int[][] arr2) {
arr = arr2; // this 없이도 가능한 경우
}
- 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
- 오버라이딩이란 메소드를 재 정의 하는 것
- 추상클래스는 재정의는 아니고 구현 하는 것
DI(Dependency Injection) → 의존성 주입
DiEx 라는 클래스에서 ShapeDrawer를 사용(의존 Depends)한다.
객체 간의 '결합도를 낮추기 위해' 사용된다.
A 객체가 B 객체에 의존한다 - 출처 백엔드 위키 5팀 '오'로나민 C
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(”순한맛 입니다");
}
}
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 클래스 다이어그램
(커뮤니티 버전은 사용 불가)
오늘은 OOP에 대해 제대로 파헤치기 시작했다. 생성자부터 추상클래스를 지나 의존성 주입까지 정말 많은 것들을 배운 시간이었다.
메소드를 시작한지 이틀 째라 익숙하지 않은 상태임에도 불구하고 강사님의 후진없는 진도는 나의 뉴런들을 파괴시키고야 말았다.
하지만 역시나 어려운 내용임에도 불구하고 갓사이트 타임을 활용해 팀원들과의 소통으로 많은 것들을 배웠다. 두시간도 안되는 시간이지만 역시 효과는 최고인 것 같다.
앞으로 Spring을 이용한 개발을 하기 위해선 OOP에 대해 빠삭해야 한다는 것쯤은 알고 있다. 시간이 좀 걸리겠지만 포기만 하지 말자 오늘도 해냈으니까.
내일도 파이팅