: 매일 저녁, 하루를 마무리하며 작성 !
: ⭕ 지식 위주, 학습한 것을 노트 정리한다고 생각하고 작성하면서 머리 속 흩어져있는 지식들을 정리 !
객체란?
객체는 세상에 존재하는 물체를 뜻하며 식별이 가능한 것을 의미
객체 간의 협력
현실 세계에서 사람이라는 객체와 자동차라는 객체는 서로 행위를 통해 상호작용을 하며 협력
소프트웨어의 객체들은 메서드를 통해 데이터를 주고받을 수도 있다, 사람 객체는 메서드를 호출할 때 괄호( ) 안에 데이터를 넣어 호출할 수 있는데 이때 이 괄호 안에 넣는 데이터를 ‘파라미터’ 혹은 ‘매개값’ 이라고 표현
객체 간의 관계
사용 관계
포함 관계
상속 관계
객체지향 프로그래밍의 특징
캡슐화 : 캡슐화란 속성(필드)와 행위(메서드)를 하나로 묶어 객체로 만든 후 실제 내부 구현 내용은 외부에서 알 수 없게 감추는 것을 의미
상속 : 객체지향 프로그래밍에는 부모 객체와 자식 객체가 존재, 부모 객체는 가지고 있는 필드와 메서드를 자식 객체에 물려주어 자식 객체가 이를 사용할 수 있도록 만들 수 있다.
다형성 : 객체가 연산을 수행할 때 하나의 행위에 대해 각 객체가 가지고 있는 고유한 특성에 따라 다른 여러 가지 형태로 재구성되는 것을 의미
추상화 : 객체에서 공통된 부분들을 모아 상위 개념으로 새롭게 선언하는 것
객체와 클래스
자동차 클래스를 통해 만들어진 하나의 자동차를 인스턴스라고 부르며 이러한 여러 개의 인스턴스들을 크게 통틀어서 자동차 객체라고 표현
public class Car {}
String company; // 자동차 회사
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격
double speed; // 자동차 속도 , km/h
char gear; // 기어의 상태, P,R,N,D
boolean lights; // 자동차 조명의 상태
public class Car {
String company; // 자동차 회사
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격
double speed; // 자동차 속도 , km/h
char gear; // 기어의 상태, P,R,N,D
boolean lights; // 자동차 조명의 상태
public Car() {} // 기본 생성자
}
public class Car {
String company; // 자동차 회사
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격
double speed; // 자동차 속도 , km/h
char gear; // 기어의 상태, P,R,N,D
boolean lights; // 자동차 조명의 상태
public Car() {} // 기본 생성자
double gasPedal(double kmh) {
speed = kmh;
return speed;
}
double brakePedal() {
speed = 0;
return speed;
}
char changeGear(char type) {
gear = type;
return gear;
}
boolean onOffLights() {
lights = !lights;
return lights;
}
void horn() {
System.out.println("빵빵");
}
}
new Car(); // Car클래스 객체 생성
Car car1 = new Car(); // Car클래스의 객체인 car1 인스턴스 생성
Car car2 = new Car(); // Car클래스의 객체인 car2 인스턴스 생성
// car class
public class Car {
String company; // 자동차 회사
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격
double speed; // 자동차 속도 , km/h
char gear; // 기어의 상태, P,R,N,D
boolean lights; // 자동차 조명의 상태
public Car() {} // 기본 생성자
double gasPedal(double kmh) {
speed = kmh;
return speed;
}
double brakePedal() {
speed = 0;
return speed;
}
char changeGear(char type) {
gear = type;
return gear;
}
boolean onOffLights() {
lights = !lights;
return lights;
}
void horn() {
System.out.println("빵빵");
}
}
// 객체 배열 main
public class Main {
public static void main(String[] args) {
Car[] carArray = new Car[3];
Car car1 = new Car();
car1.changeGear('P');
carArray[0] = car1;
Car car2 = new Car();
car2.changeGear('N');
carArray[1] = car2;
Car car3 = new Car();
car3.changeGear('D');
carArray[2] = car3;
for (Car car : carArray) {
System.out.println("car.gear = " + car.gear);
}
}
}
// 출력
//car.gear = P
//car.gear = N
//car.gear = D
필드란?
필드는 객체의 데이터를 저장하는 역할
필드의 초기값과 초기화
초기값을 제공하는 방법은 ‘필드 타입 필드명 = 값;’ 이렇게 직접 초기화
필드 사용방법
// 외부 접근
Car car = new Car();
car.color = "blue";
// 내부 접근
double brakePedal() {
speed = 0;
return speed;
}
// 선언
리턴타입 메서드명(매개변수, ...) {
실행할 코드 작성
}
// 리턴 타입
double brakePedal() {...} // double 타입 반환
char changeGear(char type) {...} // char 타입 반환
boolean onOffLights() {...} // boolean 타입 반환
void horn() {...} // 반환할 값 없음
// 매개변수
double gasPedal(double kmh, char type) {
speed = kmh;
return speed;
}
// 가변길이 매개변수
void carSpeeds(double ... speeds) {
for (double v : speeds) {
System.out.println("v = " + v);
}
}
// 외부 접근
Car car = new Car();
car.brakePedal();
car.gasPedal(100, 'D');
// 내부 접근
double gasPedal(double kmh, char type) {
changeGear(type);
speed = kmh;
return speed;
}
// 반환 값 저장
double speed = car.gasPedal(100, 'D');
오버로딩의 조건
- 메서드의 이름이 같고, 매개변수의 개수, 타입, 순서가 달라야 한다.
- '응답 값만' 다른 것은 오버로딩을 할 수 x
- 접근 제어자만 다른 것도 오버로딩을 할 수 x
- 결론, 오버로딩은 매개변수의 차이로만 구현할 수 o
오버로딩의 장점
- 메서드 이름 하나로 상황에 따른 동작을 개별로 정의할 수 o
- 메서드의 이름을 절약
public class PrintStream extends FilterOutputStream
implements Appendable, Closeable
{
...
public void println() {
newLine();
}
public void println(boolean x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(char x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(int x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(long x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(float x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(double x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(char[] x) {
if (getClass() == PrintStream.class) {
writeln(x);
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(String x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(Object x) {
String s = String.valueOf(x);
if (getClass() == PrintStream.class) {
// need to apply String.valueOf again since first invocation
// might return null
writeln(String.valueOf(s));
} else {
synchronized (this) {
print(s);
newLine();
}
}
}
...
}
기본형 매개변수
참조형 매개변수
// car class
public class Car {
String company; // 자동차 회사
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격
double speed; // 자동차 속도 , km/h
char gear; // 기어의 상태, P,R,N,D
boolean lights; // 자동차 조명의 상태
Tire tire;
Door door = new Door();
Handle handle = new Handle();
public Car() {} // 기본 생성자
double gasPedal(double kmh, char type) {
changeGear(type);
speed = kmh;
return speed;
}
double brakePedal(char type) {
speed = 0;
type = 'P'; // 정지 후 매개변수 type을 어떤 타입으로 전달 받았는지 상관없이 'P'로 고정시키기
changeGear(type);
return speed;
}
char changeGear(char type) {
gear = type;
return gear;
}
boolean onOffLights() {
lights = !lights;
return lights;
}
void horn() {
System.out.println("빵빵");
}
Tire setTire(Tire tireCompany) {
tireCompany.company = "KIA"; // 금호 타이어를 전달 받았지만 강제로 KIA 타이어로 교체
tire = tireCompany;
return tire;
}
}
// tire class
public class Tire {
String company; // 타이어 회사
public Tire() {}
}
// main class
public class Main {
public static void main(String[] args) {
Car car = new Car(); // 객체 생성
// 기본형 매개변수
char type = 'D';
car.brakePedal(type);
// 메서드 실행 완료 후 전달할 매개값으로 지정된 type 값 확인
System.out.println("type = " + type); // 기존에 선언한 값 'D' 출력, 원본 값 변경되지 않음
// 메서드 실행 완료 후 반환된 car 인스턴스의 gear 타입 확인
System.out.println("gear = " + car.gear); // 객체 내부에서 type을 변경하여 수정했기 때문에 'P' 출력
System.out.println();
// 참조형 매개변수
Tire tire = new Tire();
tire.company = "금호"; // 금호 타이어 객체 생성
// 차 객체의 타이어를 등록하는 메서드 호출한 후 반환값으로 차 객체의 타이어 객체 반환
Tire carInstanceTire = car.setTire(tire);
// 메서드 실행 완료 후 전달할 매개값으로 지정된 참조형 변수 tire의 company 값 확인
System.out.println("tire.company = " + tire.company); // "KIA" 출력
// 전달할 매개값으로 지정된 tire 인스턴스의 주소값이 전달되었기 때문에 호출된 메서드에 의해 값이 변경됨.
// 메서드 실행 완료 후 반환된 car 인스턴스의 tire 객체 값이 반환되어 저장된 참조형 변수 carInstanceTire의 company 값 확인
System.out.println("carInstanceTire.company = " + carInstanceTire.company); // "KIA" 출력
}
}
인스턴스 멤버 : 인스턴스 멤버는 객체를 생성해야 사용할 수 있다, 객체의 인스턴스 필드는 각각의 인스턴스마다 고유하게 값을 가질 수 있다.
클래스 멤버
필드와 메서드를 클래스 멤버로 만들기 위해서는 static 키워드를 사용
// 선언
static String company = "GENESIS"; // 자동차 회사 : GENESIS
String getCompany() {
return "(주)" + company;
}
static String setCompany(String companyName) {
// System.out.println("자동차 모델 확인: " + model); // 인스턴스 사용 불가
company = companyName;
return company;
}
// 사용
Car.company = "Audi";
String companyName = Car.setCompany("Benz");
Car car = new Car(); // 객체 생성
car.company = "Ferrari";
String companyName2 = car.setCompany("Lamborghini");
public class Main {
public static void main(String[] args) {
Main main = new Main();
// 메서드 호출 : main.getClass()
System.out.println("main.getClass() = " + main.getNumber());
System.out.println("main.getClass() = " + main.getNumber());
System.out.println("main.getClass() = " + main.getNumber());
}
public int getNumber() {
int number = 1; // 지역 변수
number += 1;
return number; // 메서드 종료되면 지역변수 제거됨
}
}
// 출력
//main.getNumber() = 2
//main.getNumber() = 2
//main.getNumber() = 2
// final 선언
final String company = "GENESIS";
...
Car car = new Car();
System.out.println(car.company);
// 상수
static final String COMPANY = "GENESIS";
...
System.out.println(Car.COMPANY);
public Car() {} // 선언
...
Car car = new Car(); // 호출
public Car(String model, String color, double price) {
this.model = model;
this.color = color;
this.price = price;
}
Car returnInstance() {
return this;
}
public Car(String model) {
this(model, "Blue", 50000000);
}
public Car(String model, String color) {
this(model, color, 100000000);
}
public Car(String model, String color, double price) {
this.model = model;
this.color = color;
this.price = price;
}
public Car(String model) {
System.out.println("model = " + model);
this(model, "Blue", 50000000);
}
public
: 접근 제한이 전혀 xprotected
: 같은 패키지 내에서, 다른 패키지의 자손 클래스에서 접근이 가능default
: 같은 패키지 내에서만 접근이 가능private
: 같은 클래스 내에서만 접근이 가능접근 제어자를 이용한 캡슐화 (은닉성)
: 근제어자는 클래스 내부에 선언된 데이터를 보호하기 위해서 사용, 유효한 값을 유지하도록, 함부로 변경하지 못하도록 접근을 제한하는 것이 필요
생성자의 접근 제어자
: 생성자에 접근 제어자를 사용함으로 인스턴스의 생성을 제한할 수 있다, 일반적으로 생성자의 접근 제어자는 클래스의 접근 제어자와 일치
private double speed; // 자동차 속도 , km/h
private char gear = 'P'; // 기어의 상태, P,R,N,D
private boolean lights; // 자동차 조명의 상태
// Getter
public String getModel() {
return model;
}
public String getColor() {
return color;
}
public double getPrice() {
return price;
}
// Setter
public void setModel(String model) {
this.model = model;
}
public void setColor(String color) {
this.color = color;
}
public void setPrice(double price) {
this.price = price;
}
public class 자식클래스 extends 부모클래스 {
}
// car class
public class Car {
String company; // 자동차 회사
private String model; // 자동차 모델
private String color; // 자동차 색상
private double price; // 자동차 가격
double speed; // 자동차 속도 , km/h
char gear = 'P'; // 기어의 상태, P,R,N,D
boolean lights; // 자동차 조명의 상태
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public double gasPedal(double kmh, char type) {
changeGear(type);
speed = kmh;
return speed;
}
public double brakePedal() {
speed = 0;
return speed;
}
public char changeGear(char type) {
gear = type;
return gear;
}
public boolean onOffLights() {
lights = !lights;
return lights;
}
public void horn() {
System.out.println("빵빵");
}
}
// sportscar class
public class SportsCar extends Car{
String engine;
public void booster() {
System.out.println("엔진 " + engine + " 부앙~\n");
}
public SportsCar(String engine) {
this.engine = engine;
}
@Override
public double brakePedal() {
speed = 100;
System.out.println("스포츠카에 브레이크란 없다");
return speed;
}
@Override
public void horn() {
booster();
}
}
// main
public class Main {
public static void main(String[] args) {
// 부모 클래스 자동차 객체 생성
Car car = new Car();
car.horn(); // 경적
System.out.println();
// 자식 클래스 스포츠카 객체 생성
SportsCar sportsCar = new SportsCar("Orion");
// 오버라이딩한 brakePedal(), horn() 메서드 호출
sportsCar.brakePedal();
sportsCar.horn();
}
}
// 부모 클래스 Car
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격
// 자식 클래스 SportsCar
String model = "Ferrari"; // 자동차 모델
String color = "Red"; // 자동차 색상
double price = 300000000; // 자동차 가격
// 자식 클래스의 메서드
public void setCarInfo(String model, String color, double price) {
super.model = model; // model은 부모 필드에 set
super.color = color; // color는 부모 필드에 set
this.price = price; // price는 자식 필드에 set
}
super(…)는 부모 클래스의 생성자를 호출할 수 있는 키워드
// 부모 클래스 Car 생성자
public Car(String model, String color, double price) {
this.model = model;
this.color = color;
this.price = price;
}
// 자식 클래스 SportsCar 생성자
public SportsCar(String model, String color, double price, String engine) {
// this.engine = engine; // 오류 발생
super(model, color, price);
this.engine = engine;
}
부모 타입 변수 = 자식 타입 객체;
는 자동으로 부모 타입으로 변환자식 타입 변수 = (자식 타입) 부모 타입 객체;
부모 타입 객체는 자식 타입 변수로 자동으로 타입 변환되지 않습니다. (자식 타입) 즉, 타입 변환 연산자를 사용하여 강제로 자식 타입으로 변환// 자식타입객체가 자동 타입변환된 부모타입의 변수
Mammal mammal = new Whale();
mammal.feeding();
// 자식객체 고래의 수영 기능을 사용하고 싶다면
// 다시 자식타입으로 강제 타입변환을 하면된다.
Whale whale = (Whale) mammal;
whale.swimming();
// 참조 변수 타입 변환을 활용해서 다형성을 구현
Tire tire = new HankookTire("HANKOOK");
Tire tire = new KiaTire("KIA");
// 매개변수에도 다형성이 적용
public Car(Tire tire) {
this.tire = tire;
}
...
Car car1 = new Car(new KiaTire("KIA"));
Car car2 = new Car(new HankookTire("HANKOOK"));
// 반환 타입에도 다형성이 적용
instance of
: 이 명령어를 통해 해당 객체가 내가 의도하는 클래스의 객체인지 확인{대상 객체}
instance of
{클래스 이름}
와 같은 형태로 사용하면 응답값은 booleanpublic abstract class 추상클래스명 {
}
public abstract class 추상클래스명 {
abstract 리턴타입 메서드이름(매개변수, ...);
}
public class 클래스명 extends 추상클래스명 {
@Override
public 리턴타입 메서드이름(매개변수, ...) {
// 실행문
}
}
// 벤츠 클래스
public class BenzCar {
String company; // 자동차 회사 : GENESIS
String color; // 자동차 색상
double speed; // 자동차 속도 , km/h
public double gasPedal(double kmh) {
speed = kmh;
return speed;
}
public double brakePedal() {
speed = 0;
return speed;
}
public void horn() {
System.out.println("Benz 빵빵");
}
}
// 아우디 클래스
public class AudiCar {
String company; // 자동차 회사 : GENESIS
String color; // 자동차 색상
double speed; // 자동차 속도 , km/h
public double gasPedal(double kmh) {
speed = kmh;
return speed;
}
public double brakePedal() {
speed = 0;
return speed;
}
public void horn() {
System.out.println("Audi 빵빵");
}
}
// 제네시스 클래스
public class GenesisCar {
String company; // 자동차 회사 : GENESIS
String color; // 자동차 색상
double speed; // 자동차 속도 , km/h
public double gasPedal(double kmh) {
speed = kmh;
return speed;
}
public double brakePedal() {
speed = 0;
return speed;
}
public void horn() {
System.out.println("Zenesis 빵빵");
}
}
// 카 클래스
public abstract class Car {
String company; // 자동차 회사 : GENESIS
String color; // 자동차 색상
double speed; // 자동차 속도 , km/h
public double gasPedal(double kmh) {
speed = kmh;
return speed;
}
public double brakePedal() {
speed = 0;
return speed;
}
public abstract void horn();
}
public interface 인터페이스명 {
}
public interface 인터페이스명 {
public static final char A = 'A';
static char B = 'B';
final char C = 'C';
char D = 'D';
void turnOn(); // public abstract void turnOn();
}
public class 클래스명 implements 인터페이스명 {
// 추상 메서드 오버라이딩
@Override
public 리턴타입 메서드이름(매개변수, ...) {
// 실행문
}
}
public class Main extends D implements C {
@Override
public void a() {
System.out.println("A");
}
@Override
public void b() {
System.out.println("B");
}
@Override
void d() {
super.d();
}
public static void main(String[] args) {
Main main = new Main();
main.a();
main.b();
main.d();
}
}
interface A {
void a();
}
interface B {
void b();
}
interface C extends A, B {
}
class D {
void d() {
System.out.println("D");
}
}
public class Main implements A {
@Override
public void a() {
System.out.println("A");
}
public static void main(String[] args) {
Main main = new Main();
main.a();
// 디폴트 메서드 재정의 없이 바로 사용가능합니다.
main.aa();
}
}
interface A {
void a();
default void aa() {
System.out.println("AA");
}
}
public class Main implements A {
@Override
public void a() {
System.out.println("A");
}
public static void main(String[] args) {
Main main = new Main();
main.a();
main.aa();
System.out.println();
// static 메서드 aaa() 호출
A.aaa();
}
}
interface A {
void a();
default void aa() {
System.out.println("AA");
}
static void aaa() {
System.out.println("static method");
}
}
타입 변환
인터페이스 변수 = 구현객체;는 자동으로 타입 변환
구현 객체 타입 변수 = (구현 객체 타입) 인터페이스 변수; 강제 타입 변환
인터페이스의 다형성
// LG TV 구현체를 조작
MultiRemoteController mrc = new LgTv("LG");
mrc.turnOnOff();
mrc.volumeUp();
// 조작 대상을 Samsung TV로 교체
mrc = new SamsungTv("Samsung");
mrc.turnOnOff();
mrc.channelUp();
// 매개변수와 반환타입 다형성 확인 메서드
default MultiRemoteController getTV(Tv tv) {
if(tv instanceof SamsungTv) {
return (SamsungTv) tv;
} else if(tv instanceof LgTv){
return (LgTv) tv;
} else {
throw new NullPointerException("일치하는 Tv 없음");
}
}
문제 설명
머쓱이는 선생님이 몇 년도에 태어났는지 궁금해졌습니다. 2022년 기준 선생님의 나이 age가 주어질 때, 선생님의 출생 연도를 return 하는 solution 함수를 완성해주세요
제한사항
0 < age ≤ 120
나이는 태어난 연도에 1살이며 매년 1월 1일마다 1살씩 증가합니다.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int solution(int age) {
int answer = 0;
if (0 < age && age <= 120){
for (int i=0; age >0; i++){
answer = 2022 - i;
age--;
}
}
return answer;
}