객체 지향 프로그래밍
- 프로그래밍에서 필요한 데이터를 추상화 시켜 상태와 행위를 가진 객체로 만들고,
객체들간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법- 코드의 재사용성이 높다
- 코드의 관리가 용이하다
- 신뢰성이 높은 프로그래밍을 가능하게 한다
객체와 인스턴스
- 클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화
- 어떤 클래스로부터 만들어진 객체를 그 클레스의 인스턴스라고 함
- 인스턴스는 참조변수를 통해서만 다룰 수 있으며, 참조변수의 타입은 인스턴스의 타입과 일치해야함
상속의 오해
- '공통된 기능을 여러 객체에게 전달하고 싶을 때' 라고 생각하기 쉽지만 근본적인 의도가 아님!
- 원자 > 물질 > 생물 > 동물> ... 추상화가 되야함
- new 연산자를 이용해서 객체를 직접 만들지 못하게 할 수 있음
abstract class Login {
abstract void login();
}
// abstract가 하나라도 있는 클래스는 abstract class형식
// class 자체가 추상화 목적이면 interface가 됌
인터페이스
- interface 내부에 메서드를 생성할 때 [public abstract]를 생략하더라도 컴파일 과정에서 자동으로 붙게 됌
- void longin(); => [public abstract] void longin();
NaverLogin implements Portal, Login 구조
Login login = new NaverLogin();
login.login(); //로그인만 호출 가능
Portal portal = new NaverLogin();
portal.portal(); // 포털만 호출 가능
//같은 객체라도 필터링된 필요한 기능만 접근할 수 있게 할 수 있음
//즉 캡슐화 업무분리가 가능해짐
//100가지 기능이 있으면 90개는 private으로 만들고 다른 객체에 각각 7개 3개를 제공할 수 있음
Login user = getLogin(LoginType.Kakao);
private static Login getLogin(LoginType type) {
if (type == LoginType.Kakao) return new KakaoLogin();
return new NaverLogin();
}
// 이런식으로 같은 인터페이스를 받는 객체들을 get메서드를 통해 할당할 수 있음
public enum LoginType{
Kakao, Naver
}
// enum을 정의해서 가독성을 높일 수 있음
public class UserService implements Login {
Login login;
(생성자)
@Override
public void login() {
login.login();
}
}
UserService s = new UserService(new KakaoLogin());
s.login();
// 서비스 정의를 통해 객체를 넣어주는 형태로 작성
어댑터
class MyInterfaceAdapter implements MyInterface {
@Override
public void method1() {
}
@Override
public void method2() {
}
}
class Service extends MyInterfaceAdapter {
@Override
public void method1() {
}
}
// 원하는 메서드만 구현하고 싶을때 어댑터 사용
// 이미 상속 받고 있는 것이 있으면 문제가 생김
// interface 생성시 default를 통해 Adapter역할 가능 (Java 8 이상)
public interface MyInterface {
default void method1() {}
default void method2() {}
} // 이렇게 하면 상속시 method1()만 오버라이딩 할 수 있음
함수형 인터페이스
// 추상메소드가 하나밖에 없는 메소드 == 함수형 인터페이스
// default, static 메소드가 있고 추상메소드가 하나인 인터페이스면 함수형 인터페이스이다
@FunctionalInterface를 달아준다
// 익명 클래스
// interface MySupply{}
new MySupply() {
@Override
public String supply() {
return "hello";
}
}.supply();
// 익명 클래스 생략
// FuntionalInterface잖아
// Override 하는거 알고
// new를 통해 생성하는 것 알고
// public 알고
// void run()에 인자 없는거 알고 void run() -> () 으로 바뀜
// 구분을 해주자 -> 표시
// 한줄 밖에 없으면{} 생략
new MyRunnable() {
@Override
public void run() {
System.out.println("Hello");
}
}
// 아래 형식으로 바뀔 수 있음
// return이면 return 생략
MyRunnable r = () -> System.out.println("Hello");
// 매개변수 있으면
(str) -> str.length(); // 이런식으로 표현
String::length; //위의 식을 변환 -> String이 들어와서 바로 length를 사용할거다
// 메소드 레퍼런스
// 람다 표현식에서 입력되는 값을 변경없이 바로 사용하는 경우 생략 방식
// 개발자의 개입을 차단함으로써 안정성을 얻을 수 있다
// 제네릭타입
public interface MyMapper<IN, OUT>{
OUT map(IN s);
}
MyMapper<String, Integer>
// 메소드 레퍼런스를 활용해서 어떤 동작을 할지에 대한 결정을 분리하는 법
new Main().loop(10, System.out::println);
void loop(int n, MyConsumer<Integer> consumer {
for (int i = 0; i < n; i++) {
consumer.consume(i);
}
}
'프로그래밍 > JAVA' 카테고리의 다른 글
[Java] Optional (0) | 2024.03.30 |
---|---|
[Java] 메서드 참조 (0) | 2024.03.30 |
[Java] Generics (0) | 2024.03.30 |
[Java] Enum (0) | 2024.03.30 |
[Java] Collections (0) | 2024.03.30 |