자바 기본 지식 (2)

리진아·2023년 1월 13일
0
post-thumbnail

요 파트는 익숙한 부분에 실제로 공부도 했었기 때문에 빠르게 읽고 넘어갔다.


✔︎ 객체지향 확장

자바가 객체 지향을 확장하기 위해 사용하는 키워드

1️⃣ abstract

✔︎ 추상 메서드 : 선언부는 있는데 구현부가 없는 메서드
추상화 : 클래스간의 공통점을 찾아내서 공통의 부모를 설계하는 작업
구체화 : 상속을 통해 클래스를 설계, 확장하는 작업

public class Driver{
	public static void main(String[] args){
    	몬스터[] 몬스터들 = new 몬스터[3];
        
        몬스터들[0] = new 좀비();
        몬스터들[1] = new 스켈레톤();
        몬스터들[2] = new 크리퍼();
        몬스터들[3] = new 엔더맨();
        for (int i=0; i<몬스터들.length; i++){
        	몬스터들[i].공격하세요();
        }
    }
}
public class 좀비 extentds 몬스터{
	//void 공격하세요(){
    //	sout("손으로 때린다");
    //}
}
public class 스켈레톤 extentds 몬스터{
	//void 공격하세요(){
    //	sout("화살을 쏜다");
    //}
}
public abstract class 좀비{
	abstract void 공격하세요();
}

추상 클래스는 객체(new 사용)를 만들 수 없음
추상 메서드는 하위 클래스에게 메서드의 구현을 강제(오버라이딩 강제)
추상 메서드를 포함하는 클래스는 반드시 추상 클래서여야 함

2️⃣ 생성자

✔︎ constructor : new 연산자를 통해서 인스턴스를 생성할 때 반드시 호출이 되고 제일 먼저 실행되는 일종의 메소드

  • 자바는 기본으로 생성자를 만듦. 개발자가 인자가 있는 생성자를 하나라도 만들면 기본생성자 안 만듦.
public class 사람{
	public 사람(){} //매개변수가 없는 기본 생성자
    
    public 사람(String name){ //매개변수가 있는 생성자
    	this.name = name;
    }
    
    public void show(){
    	sout("사람의 이름은 "+name+"입니다");
    }
}

public class 호출{
	public static void main(String[] args){
    		사람 사1 = new 사람(); //객체생성 - 기본생성자 호출
            사람 사2 = new 사람("이진아"); //객체생성 - 매개변수를 가진 생성자 호출1.show();2.show();
    }
}
            

3️⃣ static블록

Static이라는 키워드를 사용하여 Static 변수와 Static 메소드를 만들 수 있는데 다른 말로 정적 필드와 정적 메소드라고도 하며 이 둘을 합쳐 정적 멤버라고 함.

//메서드 사용
class Name{
    static void 이진아() { //클래스 메소드
	System.out.println("나는 이진아");
    }
    
    void 강아지() { //인스턴스 메소드
	System.out.println("나는 강아지");
    }
}

public class Static{
	
    public static void main(String[] args) {
    
        Name.이진아(); //인스턴스를 생성하지 않아도 호출이 가능
    	
        Name name = new Name(); //인스턴스 생성
        name.강아지(); //인스턴스를 생성하여야만 호출이 가능
    }
}

4️⃣ final

final은 클래스, 변수, 메서드에서만 나타낼 수 있음

//𝟙 클래스
public final class 고양이{ } //상속을 허락하지 않음. 하위 클래스 생성XX

//𝟚 변수
public class 고양이{
	final static int 정적상수1 = 1;
    final static int 정적상수2;
    final int 객체상수1 = 1;
    final int 객체상수2;
    
    static{
    	정적상수2 = 2; //상수는 한 번 초기화하면 값을 변경XX
    }
    고양이(){
    	객체상수2 = 2; //상수는 한 번 초기화하면 값을 변경XX
        final int 지역상수1 = 1;
        final int 지역상수2;
        
        지역상수2 = 2;
    }
    
//변경 불가능한 상수가 됨.
//정적상수는 선언 시 static 블록 내부레서 초기화 ㄱㄴ
//객체상수도 인스턴스 블록에서 초기화 ㄱㄴ
}

//𝟛 메서드
public class 동물{
	final void 숨쉬다(){
    	sout("호흡 중");
    }
}
class 포유류 extends 동물 {
//에러발생 : cannot override the final method from 동물
	void 숨쉬다(){
    	sout("호흡 중");
    }
}

5️⃣ instanceof 연산자

✔︎ instanceof 연산자는 객체 타입을 확인하는 연산자
사용 형식은 "객체+instanceof+클래스"

3번째 결과가 false인 이유는 부모가 있어야 자식이 있는데 자식이 부모를 되려했기 때문

6️⃣ package 키워드

네임스페이스(이름공간)를 만들어주는 역할
같은 클래스 이름을 써도 ㄱㅊ

7️⃣ interface, implements

✔︎ 인터페이스 : 추상 메서드만을 가질 수 있고 구현 메서드는 가질 수 없는 일종의 추상 클래스

인터페이스는 interface 키워드를 통해 선언할 수 있으며 implements 키워드를 통해 일반 클래스에서 인터페이스를 구현할 수 있음

< 인터페이스 특징 >
1. 다중 상속 가능
2. 추상 메서드와 상수만 사용 가능
3. 생성자 사용 불가
4. 메서드 오버라이딩 필수

public interface Animal {
    public static final String name = "동물";
    
    public abstract void move();
    public abstract void eat();
    public abstract void bark();
}
//인터페이스에는 static, final 상수와 abstract 추상 메서드만 사용


//개 클래스
public class Dog implements Animal{
    
    @Override
    public void move() {
        System.out.println("슥슥~~");
    }
    
    @Override
    public void bark() {
        System.out.println("멍멍!");
    }
}
//Animal 인터페이스를 implements 키워드로 구현하고 인터페이스의 추상 메서드들을 모두 재정의


//고양이 클래스
public class Cat implements Animal{ 

    @Override
    public void move() {
        System.out.println("사뿐사뿐~~");
    }
    
    @Override
    public void bark() {
        System.out.println("야옹~~");
    }
}
// 인터페이스의 추상 메서드들을 오버라이드 


public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        
        dog.move();
        dog.bark();
        
        cat.move();
        cat.bark();
    }
}

결과 ->
슥슥
멍멍
사뿐사뿐
야옹

8️⃣ this

✔︎ 객체가 자기 자신을 지칭할 때 쓰는 키워드

public class People{
  //필드
  int age;
  //메소드
  void setAge(int age){
    this.age = age;
  }
}

9️⃣ super

✔︎ 단일 상속만을 지원하는 자바에서 super는 바로 위 상위 클래스의 인스턴스를 지칭하는 키워드


✔︎ 객체 지향 설계 5원칙 - SOLID

SRP - 단일 책임 원칙
OCP - 개방 폐쇄 원칙
LSP - 리스코프 치환 원칙
ISP - 인터페이스 분리 원칙
DIP - 의존 역전 원칙

1️⃣ SRP (단일 책임 원칙)

남자라는 클래스는 여자친구와 헤어졌을 때 기념일챙기기(), 키스하기()를 못하게 됨
-> 때문에 이런 경우 역할(책임)을 분리하는 것이 단일 책임 원칙

남자라는 하나의 클래스가 역할과 책임에 따라 네 개 클래스로 쪼개짐

class 강아지{
	final static Boolean 수컷 = true;
    final static Boolean 암컷 = false;
    Boolean 성별;
    
    void 소변보다(){
    	if(this.성별 == 수컷){
        	//한쪽 다리를 들고 소변을 본다.
        }else{
        	//뒷다리 두 개를 굽혀 앉은 자세로 소변을 본다.
        }
    }
}

소변보다() 메서드가 수컷 강아지의 행위와 암컷 상아지의 행위를 모두 구현하려고 하기에 단일 책임 원칙을 위배하고 있는 것.

abstract class 강아지{
	abstract void 소변보다()
}
class 수컷강아지 extends 강아지{
	void 소변보다(){
    	//한쪽 다리를 들고 소변을 본다
    }
}
class 암컷강아지 extends 강아지{
	void 소변보다(){
    	//뒷다리 두 개로 앉은 자세를 소변을 본다.
    }
}

단일 책임 원칙을 적용해 코드를 리팩터링 하였다.

2️⃣ OCP (개방 폐쇄 원칙)

운전자가 마티즈를 구입하여 적응한 후 쏘나타를 구입하였는데 창문과 기어를 수동에서 자동으로 바뀌어 운전 습관을 바꿔야만 함.

상위클래스 또는 인터페이스를 중간에 둠으로써 다양한 차종을 변경하더라도 운전자는 운전 습관에 영향을 받지 않아도 됨.

개방 폐쇄 원칙은 db를 개발할 때 아주 좋음

JDBC를 사용하는 클라이언트는 DB가 오라클에서 MySQL로 바뀌더라도 Connection을 설정하는 부분외에는 따로 수정할 필요X

3️⃣ LSP (리스코프 치환 원칙)

자바에서 객체 지향의 상속은
하위 분류는 상위 분류의 한 종류이고, 구현 분류는 인터페이스 할 수 있어야 함.
그러나,

아버지(상위 클래스)와 딸(하위 클래스)이 있다고 가정했을 때
상위클래스의 객체 참조 변수에는 하위 클래스의 객체를 할당할 수 있다.

아버지 춘향이 = new 딸()

춘향이는 아버지형 객체 참조 변수이기에 아버지가 가진 메서드를 할 수 있어야 하는데 춘향이는 아버지의 메서드 행위를 할 수 없다.
반대로,

동물 뽀로로 = new 펭귄()

펭귄 한 마리가 태어나 뽀로로라 이름을 짓고 동물의 메서드를 사용해도 이상이 없다.

✔︎ 아버지 - 딸 구조(계층도/조직도)는 리스코프 치환 원칙을 위배하고 있는 것,
✔︎ 동물 - 펭귄 구조(분류도)는 리스코프 치환 원칙을 만족하는 것.

4️⃣ ISP (인터페이스 분리 원칙)

단일 책임 원칙에서 남자라는 클래스를 분리하여 하나의 역할(책임)만 하는 다수의 클래스로 분할하는 것.
->

위 사진처럼 남자라는 클래스를 다중 인격화시켜 역할을 부여함.

빈약한 상위클래스를 이용할 경우 형변환이 일어나면서 상속의 혜택을 누릴 수 없게 됨.
풍성한 상위클래스를 이용할 경우 사용 불가능한 경우나 불필요한 형변환이 없음.

5️⃣ DIP (의존 역전 원칙)

자동차 -----> 스노우타이어

자동차는 스노우타이어에 의존한다. 그러나 자동차는 한 번 사면 오랜기간 사용하지만 스노우 타이어는 계절이 바뀌면 일반 타이어로 교체한다. 이런 경우 자동차는 스노우 타이어를 교체할 때 영향에 노출돼 있다. 따라서

타이어가 변경되어도 자동차는 그 영향을 받지 않게 된다. 기존에는 스노우 타이어가 무엇에도 의존하지 않던 클래스였지만, 추상적인 것인 타이어 인터페이스에 의존하게 되었다. 이처럼 자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것에 영향을 받지 않게 하는 것이 의존 역전 원칙이다.

profile
알맹이가 가득 찬 개발자가 되기 위해 한 걸음 더 다가가는,

0개의 댓글