일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- aws #아키텍트 #과정 #vpc #인프라 구축 #public subnet #route53 #igw #연결
- tar #build #배포 #통신포트 #설정방법 #linux #apache
- aws #아키텍트 #과정 #vpc #인프라 구축 #public subnet #internet gateway #연결
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #웹개발
- 공간복잡도 #공간자원 #캐시메모리 #SRAM #DRAM #시간복잡도
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #딥러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #DBMS #Oracle #MongoDB #아키텍쳐 #DB
- samba #가상머신 #daemon
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #딥러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스
- 쓰레드 #쓰레드풀 #프로세스
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #OSI #ISO #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #DBMS #Oracle #MongoDB #아키텍쳐 #DB
- 인바운드 #아웃바운드 #방화벽설정
- haproxy #wordpree #php #linux #가상화 #가상머신 #내용정리
- storage #로컬스토리지 #세션스토리지 #백그라운드 서비스
- 비트 #바이트 #이진수
- aws #아키텍트 #과정 #vpc #인프라 구축 #public subnet #igw #curl #명령어 #http
- sasac #aws 클라우드 #아키텍트 과정 #가상화 #vmbox #vmware #esxi #tar #selinux
- aws #아키텍트 #과정 #vpc #인프라 구축
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스
- aws #아키텍트 #과정 #vpc #인프라 구축 #public subnet #private subnet
- aws #아키텍트 #과정 #vpc #인프라 구축 #php #웹페이지 #http #public #instance
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #KDT #기본문법 #데이터베이스 #Computer #Science #CPU #메모리
- mysql #linux #설정 #wordpress #웹사이트 #db 연결 #
- aws #클라우드 #퍼블릭 클라우드 #아키텍트 #과정
- oracle vmbox #rocky #linux9 #명령어 #암호화인증 #해시알고리즘
- 프로세스 #CPU #시공유 #커널
- aws #아키텍트 #과정 #s3 #bucket #생성 #이미지업로드
- ubuntu #설정변경 #vmware #vmbox #linux #명령어
- virtualbox #vmware #router #nat #pat #네트워크 구성도 #aws #ubuntu #
- aws #아키텍트 #과정 #vpc #인프라 구축 #퍼블릭 서브넷 #안에 #ec2 인스턴스 #ami #생성 #firewall
- aws #아키텍트 #과정 #vpc #인프라 구축 #퍼블릭 #보안그룹 #생성 #http #ipv4
- Today
- Total
요리사에서 IT개발자로
스파르타 코딩클럽 부트캠프 (Java 문법 3장) 본문
객체지향 프로그래밍이란
소프트웨어가 필요한 부품들을 제작하여 부품들을 조립해서 하나의 완성된 프로그램을 만들 수 있는것.
객체란?
객체는 세상에 존재하는 물체를 뜻하며 식별이 가능한 것.
객체는 속성과 행위로 구성이 되어있다.
예를 들자면
속성 = 회사, 모델, 색상, 가격, 속도 등
행위 = 가속, 브레이크, 기어 변속, 조명 ,경적
Java에서는 위와같은 속성과 행위를 필드의 메서드로 정의하여 구현할 수 있다.
이와 같은 현실에있는 객체를 소프트웨어의 객체로 설계하는 것을
객체 모델링이라 한다.
현실에서 사람이라는 객체와 자동차라는 객체는 서로 행위를 통하여 상호작용을 하며 협력할 수 잇다.
자동차의 가속 페달을 밟는다 => 이에 자동차가 반응하며 속도가 올라간다.
자동차의 브레이크 페달을 밟는다 => 이에 자동차가 반응하며 속도를 줄인다.
왼쪽에 Person(사람)이 Car의 gasPedal()을 호출한다 => Car는 이에 반응하여 가지고있는 값을 보낸다.
왼쪽에 Person(사람)이 Car의 brakePedal()을 호출한다 = >Car는 이에 반응하여 가지고 있는 값을 보낸다.
소프트 웨어의 객체들은 메서드를 통해 데이터를 주고받을 수 있다.
Person은 Car의 메소드를 호출할 때
괄호 안에 넣는 데이터를
파라미터 혹은 매개값
이라 표현한다.
- Person은 gasPedal(50); 처럼 메서드 괄호 안에 50의 매개값을 넣어 호출한다.
- Car는 50의 데이터를 전달받아 행위 gasPedal에 입력하여 속도의 값을 50으로 만든다.
- Car는 gasPedal(50); 메소드에서 입력값을 수행한 후
- Person에게 실행결과인 속도의 값을 보여주는데 이를 리턴값이라한다.
객체 간의 관계
Person은 Car객체를 사용하는
'사용의 관계'를 맺고있다.
포함관계
Tire, Door, Handle은 Car객체에 포함되어 있다.
상속 관계
회사에서는 Car만 생산하는게 아닌 Train도 생산한다면
Car와 Train 객체는 하나의 공통 기술 시스템을 토대로 만들어진다면?
Car와 Train은 회사의 기술자체를 상속받는 상속관계가 된다.
객체 지향 프로그래밍 특징
캡슐화
- 속성 (필드)와 행위(메서드)를 하나로 묶어 만든 후 실제 내부 구현내용이 외부에서 알 수 없게 감추는 것
- 외부 객체에서는 캡슐화 된 객체의 내부 구조를 알 수 없기에 노출시켜준 필드 혹은 메서드를 통해 접근할 수 있다.
- 필드와 메서드를 캡슐화하여 숨기는 이유는 외부 객체에서 해당 필드와 메서드를 잘못 사용하여 객체가 변화하지 않게 하는데 있다.
- Java에서는 캡슐화 된 캑체의 필드와 메서드를 외부에 노출될지를 결정하기 위해 접근제어자를 사용한다.
상속
객체지향 프로그래밍에는 부모객체, 자식 객체가 존재한다.
부모 객체는 가지고 있는 필드와 메서드를 자식 객체에 물려주어 자식객체가 사용할 수 있게 만들었다.
위 같은 개념을 상속이라 할 수 있다.
상속을 하는 이유
- 각각의 객체들을 상속 관계로 묶음으로 객체 간의 구조를 파악하기 쉬워진다.
- 필드와 메서드를 변경하는 경우 부모 객체에 있는 것만 수정하게 되면 자식 객체에 전부 반영이 됨으로 유지보수가 쉽다.
- 자식 객체가 부모 객체의 필드와 메서드를 물려받아 사용할 수 있기에 코드 재사용이 증가한다.
다형성
객체가 연산을 수행할 때
하나의 행위에 대해 각 객체가 가지고 있는 고유한 특성에 따라서
다른 여러가지 형태로
재구성이 되는것을 의미한다.
- Car클래스 토대로 객체를 생성한다.
- CarA와 CarB의 horn()이 다르다.
- Car horn();의 메서드를 상속받아 다르게 구현하여 사용할 수 있기 때문이다.
추상화
객체에서 공통된 부분들을 종합하여 상위 개념으로 선보이는 것을 추상화라한다.
공통적이며 중요한 것들을 종합하여 객체를 모델링한다.
자동차들이 공통적으로 갖고있는
가속, 브레이크, 속도와 같은 것들을 모아
Car객체를 모델링 할 수 있다.
객체와 클래스
- 객체를 생성하기 위해서는 설계도가 필요하다.
- 설계도 없이는 자동차를 생산할 수 없다.
- 소프트웨어도 마찬가지로 설계도에 해당하는 클래스가 필요하다.
- 이때 클래스를 토대로 생성된 객체를 해당 클래스의 '인스턴스'라고 하며 이 과정을 '인스턴스화'라 한다.
- 동일한 클래스로 여러 개의 인스턴스를 구현할 수 있다.
이때 객체와 인스턴스는 거의 비슷한 표현이나 자세하게 구분하면 아래와 같다.
자동차 클래스를 통해 만들어진 하나의 자동차를 인스턴스라 하며
이러한 여러 개의 인스턴스들을 크게 통틀어 자동차 객체라 표현한다.
객체란 여러 개의 부품들이 조합하여 만들어진 소프트웨어
클래스란 객체를 생성하기 위한 설계도
클래스를 만들기 위한 과정
- 만들려고 하는 설계도(클래스)를 선언한다.
- 객체가 갖고 있어야 할 속성(필드)을 정의한다.
- 객체를 생성하는 방식을 정의한다.(생성자)
- 객체가 가지고 있어야 할 행위(메서드)를 정의한다.
package Week3;
// 1.만들려고 하는 설계도를 선언한다.(클래스 선언)
// 2.객체가 가지고 있어야할 속성(필드)를 정의한다.
// 3.객체를 생성하는 방식을 정의한다(생성자) => 생성자는 영어로 construct
// 4.객체가 가지고 잇어야할 상위(메서드)를 정의한다.
public class Car {
//<필드 영역>
// 1) 고유 데이터 영역.
String company; //자동차회사
String model = "Gv80"; //자동차 모델
String color; //자동차 색상
double price; //자동차 가격
//2) 상태 데이터 영역
double speed; //자동차 속력 km/h
char gear; //기어(P, R, N, D) 상태
boolean lights = true; //자동차 조명의 상태 (True, false)
//3) 객체 데이터 영역
Tire tire = new Tire();
Door door;
Handle handle;
//<생성자 영역>
//생성자 : 처음 객체가 생설될 때 (instance화) 어떤 로직을 수행해야하며, 어떤 값이 함수로 들어와야 하는지 정의
public Car() {
//logic
//기본생성자 : 생략이 가능하다.
System.out.println("생성자가 호출되었습니다. 객체를 생성합니다");
}
//<메서드 영역>
// gasPeDal : Kmh
// output : speed
double gasPedal(double kmh, char type){
changeGear(type); //가속도 폐달을 밟으면 자동으로 기어가 변한다.
speed = kmh;
return speed;
}
//brakePedal
//input : x
//output : speed
double brakePedal(){
speed = 0;
return speed;
}
//changGgear
//input : gear(char type)
//output : gear
char changeGear (char type){
gear = type;
return gear;
}
//onOffLight
//input : x
//output: light(boolean)
boolean onOffLight(){
lights = !lights;
return lights;
}
//hone
//input : x
//output : x
void horn(){
System.out.println("빵 빵");
}
//자동차의 속도 .. 가변길이 메서드
void carSpeeds(double ... speeds){
for(double v : speeds){
System.out.println("v = " + v);
}
}
}
package Week3;
public class Door {
public Door(){
System.out.println("문 객체가 생성되었습니다.");
}
}
package Week3;
public class Handle {
public Handle (){
System.out.println("핸들객체가 만들어졌습니다.");
}
}
package Week3;
public class Tire {
public Tire () {
System.out.println("타이어가 생성되었습니다.");
}
}
package Week3;
import java.lang.reflect.Type;
public class Main {
public static void main(String[] args) {
Car car = new Car();
System.out.println("페달 밟기 전 car.gear" + car.gear);
//메서드 호출 및 변환값을 저장
double spped = car.gasPedal(100,'D');
System.out.println("speed =" + spped);
boolean lights = car.onOffLight();
System.out.println("lights= " + lights);
System.out.println();
System.out.println("car.gear = " + car.gear);
System.out.println();
car.carSpeeds(100, 80);
System.out.println();
car.carSpeeds(110, 120, 150);
}
}
필드란
객체의 데이터를 저장하는 역할
객체의 필드는 고유 데이터, 상태 데이터, 객체데이터로 분류할 수 있다.
위 처럼 Car객체는 4개의 고유 데이터, 3개의 상태 데이터, 3개의 객체 데이터를 가질 수 있다.
필드의 초기값과 초기화
정의하여 선언한 클래스의 필드들은
default값으로 초기화 되어있다.
제공하는 방법
필드 타입 필드명 = 값 Ex)String model ="Gv80";
필드 타입별 기본값
- byte = 0
- short = 0
- int = 0
- long = 0L
- float = 0.0F
- double = 0.0
- char = \u0000
- boolean = false
- 배열 = null
- 클래스 = null
- 인터페이스 = null
필드 사용방법
클래스는 설계도 일뿐이라
실제로 필드의 데이터를 가지고있는 것은 객체이다.
객체를 생성한 후 필드를 사용할 수 있다.
외부접근은 Car의 객체를 Import하여 Car car = new Car();를 주어 객체를 생성하여 사용할 수 있다.
이때 객체의 내부 필드에 접근하는 방법은
도트(.) 연산자를 사용하면된다.
외부에서 객체 내부에 접근할 수 있고 객체 내부 메서드에서도 내부 필드에 접근할 수 있다.
//클래스의 생성자
public Car() {}
// 자동차 객체의 생성 방식을 선언한다.
//생성자는 반환타입이 없고 이름은 클래스의 이름과 동일하다.
// 괄호() 안에 아무것도 없는 생성자를 기본 생성자라 한다.
//클래스의 메서드
double gasPedal(double kmh) {
speed = kmh;
return speed;
}
//반환 타입이 double인 gasPedal(double kmh) 메서드를 선언하면
//매개변수인 kmh을 통하여 매개값을 전달받아 자동차 속성 speed 필드에 해당값을 저장한다.
double brakePedal(){
speed = 0;
return speed;
}
//반환 타입이 double인 brakePedla() 메서드를 선언한다.
//메서드가 호출되면 자동차의 속성 speed 필드의 값을 0으로 바꾸고 return한다
char changeGear(char type){
gear = type;
return gear;
}
//반환 타입이 char인 changeGear(char type) 메서드를 선언한다.
//매개변수 type을 통하여 매개값을 전달받고 메서드가 호출되면 gear필드에 해당값을 저장한다.
boolean onOffLights(){
lights = !lights;
return lights;
}
//반환 타입 boolean인 onOffLights() 메서드를 선언한다.
// 메서드가 호출되면 자동차의 속성인 lights의 현재 논리 값true, false를 반전시키고 lights값을 return한다.
void horn(){
System.out.println("빵빵");
}
//반환값이 없는 horn()메서드를 선언한다.
// 메서드가 호출되면 "빵빵"이 출력된다
메서드란
객체의 행위를 뜻하며 객체 간의 협력을 위해서 사용이된다.
메서드의 행위를 정의하는 방법
리턴 타입 메서드명 (매개변수, ...) {
실행할 코드 작성
}
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("빵빵");
}
리턴 타입이란 메서드가 실행된 후 호출을 한 곳으로 값을 반환 할때 해당 값의 타입을 의미한다.
- 주의할 점은 메서드에 리턴 타입을 선언하여 반환할 값이 있다면
- 반드시 return문으로 반환값을 지정해야한다. Ex) return 반환값.
- 반환 할 값이 없을 때는 리턴 타입의 void를 작성해야한다.
- 반환값이 없음으로 return문을 반드시 지정할 필요는 없다.
- 메서드는 실행될 때 return문을 만나면 그대로 종료한다.
- void타입일때 return; 이렇게 return문을 사용하여 원하는 지점에서 메서드를 종료할 수 있다.
매개변수
메서드를 호출할 때 메서드를 전달하려는 값을 받기위해 사용되는 변수
public double gasPedal(double kmh, char type) {
changeGear(type);
speed = kmh;
return speed;
}
위 gasPedal(double kmh, char type)메서드의 매개변수는 double타입의 kmh, char타입의 type이다.
해당 매개변수에 값을 전달하기 위해 순서와 타입에 맞춰 값을 넣어주면된다.
- gasPedal(100, 'D')
- 전달 할려는 값이 없다면 생략도 가능하다.
가변길이의 매개변수도 선언할 수 있다.
//자동차의 속도 .. 가변길이 메서드
void carSpeeds(double ... speeds){
for(double v : speeds){
System.out.println("v = " + v);
}
}
double ... speeds 이렇게 ...을 사용하면
System.out.println();
car.carSpeeds(100, 80);
System.out.println();
car.carSpeeds(110, 120, 150);
carSpeeds는 갯수 상관없이 전달이 가능하다.
메서드 호출방법
외부접근
Car car = new Car();
Car을 이용하여
외부에서 객체 내부의 메서드에 접근하며 호출할 수 있다.
이때 도트 (.) 를 연산자를 사용하면된다.
double spped = car.gasPedal(100,'D');
System.out.println("speed =" + spped);
boolean lights = car.onOffLight();
System.out.println("lights= " + lights);
또한 메서드가 매개변수를 갖고 있다면 호출할 때
매개변수의 순서와 타입에 맞게 매개값을 넣어줘야한다.
double gasPedal(double kmh, char type){
double spped = car.gasPedal(100,'D');
도트 연산자(.) 를 사용하여
외부에서 객체내부에 접근할 수 있지만
객체 내부 메서드에서도 내부 메서드에 접근하여 호출할 수 있다.
double gasPedal(double kmh, char type){
changeGear(type); //가속도 폐달을 밟으면 자동으로 기어가 변한다.
speed = kmh;
return speed;
}
gasPedal(double kmh, char type) 메서드 내부에 해당 객체 chageGear(type); 메서드를 호출 할 수 있다.
반환값 저장
리턴타입을 선언하여 반환할 값이 있다면
변수를 사용하여 받을 수 있다.
리턴타입과 변수 타입이 동일하거나 자동 타입 변환 될 수 있어야한다.
double spped = car.gasPedal(100,'D');
- double 타입의 변수 speed를 사용하여
- double gasPedal(double kmh, char type) 메서드의
- double 타입의 반환값을 받아 저장할 수 있다.
package Week3.superExample;
public class Car {
String company; // 자동차 회사
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격
double speed; // 자동차 속도 , km/h
char gear = 'P'; // 기어의 상태, P,R,N,D
boolean lights; // 자동차 조명의 상태
public String getModel() {
return model;
}
public String getColor() {
return color;
}
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("빵빵");
}
}
package Week3;
import java.lang.reflect.Type;
public class Main {
public static void main(String[] args) {
Car car = new Car();
System.out.println("페달 밟기 전 car.gear" + car.gear);
//메서드 호출 및 변환값을 저장
double spped = car.gasPedal(100,'D');
System.out.println("speed =" + spped);
boolean lights = car.onOffLight();
System.out.println("lights= " + lights);
System.out.println();
System.out.println("car.gear = " + car.gear);
System.out.println();
car.carSpeeds(100, 80);
System.out.println();
car.carSpeeds(110, 120, 150);
}
}
메서드 오버로딩이란
함수가 하나의 기능만을 구현하는 것이 아닌 메서드 이름으로 여러기능을 구현토록 하는 Java의 기능
- 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있다.
- 매개변수의 개수 또는 타입, 순서가 다르다면
- 동일한 이름을 사용해서 메서드를 정의할 수 있다.
오버로딩의 조건
- 메서드의 이름이 같고, 매개변수의 개수, 타입 ,순서가 달라야한다.
- 응답 값만 가능하고 다른 것은 오버로딩 할 수 없다.
- 접근 제어자만 다른 것도 오버로딩 할 수 없다.
- 오버로딩은 매개변수의 차이로만 구현할 수 있다.
오버로딩의 장점
- 메서드 이름 하나로 상황에 따른 동작을 개별로 정의할 수 있다.
- Ex) println() = 매개변수 int, double, String, boolean 등 넣을 수 있다.
- 메서드의 이름을 절약할 수 있다.Ex)println(), printlnInt(), printlndDouble()처럼 메서드 명이 점점 길어진다.
기본형 매개변수
- 매개변수의 타입이 기본형 일때는 값 자체가 복사되어 넘어가기에 매개값으로 지정된 변수의 원본값은 변경되지않는다.
참조형 매개변수
- 값이 저장된 곳의 원본주소를 알기에 값을 읽어오고 값을 변경하는 것도 가능하다.
- 메서드의 매개변수뿐만 아니라 반환 타입도 참조형이 될 수 있다(return)
package Week3.parameter;
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;
}
}
package Week3.parameter;
public class Tire {
String company;
public Tire() {
}
}
package Week3.parameter;
public class Main {
public static void main(String[] args) {
Car car = new Car();
char type = 'D';
car.brakePedal(type);
System.out.println("type = " + type);
System.out.println("gear = " + car.gear);
System.out.println();
Tire tire = new Tire();
tire.company = "금호";
Tire carInstanceTire = car.setTire(tire);
System.out.println("tire.company = " + tire.company);
System.out.println("carInstanceTire.company = " + carInstanceTire.company);
}
}
인스턴스 멤버와 클래스 멤버
멤버 = 필드 + 메서드
인스턴스 멤버 = 인스턴스 필드 + 인스턴스 메서드
클래스 멤버 = 클래스 필드 + 클래스 메서드
필드와 메서드는 선언하는 방법에 따라 인스턴스와 클래스로 구분할 수 있다.
인스턴스 멤버는 객체 생성 후에 사용할 수 있고
클래스 멤버는 객체 생성 없이 사용할 수 있다.
클래스는 Java의 클래스 로더에 의해 메서드 영역에 저장되고 사용된다.
클래스 멤버는 객체의 생성 필요 없이 바로 사용이가능하다.
Static 키워드를 사용하면된다.
- 클래스 멤버로 선언된 메서드는 인스턴스 멤버를 사용할 수 없다.
- 인스턴스 멤버로 선언된 메서드는 클래스 멤버를 사용할 수 없다.
- 클래스 멤버는 객체 생성 없이 바로 사용이 가능하기에
- 객체가 생성되어야 존재할 수 잇는 인스턴스 멤버를 사용할 수 없다.
static String company = "GENESIS"; // 자동차 회사 : GENESIS
- Car클래스의 Company는 GENESIS로 고정되었다.
- Car클래스를 필드로 만들어 공유한다.(메모리 효율 증가)
- 인스턴스 메서드 gtetCompany()클래스 필드 company를 사용가능하다.
static String setCompany (String companyName) {
//System.out.println("자동차 모델 확인 : " + model)
company = companyName;
return comany; // 자동차 모델 확인 : GENESIS 출력
}_
package Week3.staticFolder;
public class Car {
static String company = "GENESIS"; // 자동차 회사 : GENESIS
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격
double speed; // 자동차 속도 , km/h
char gear; // 기어의 상태, P,R,N,D
boolean lights; // 자동차 조명의 상태
public Car() {} // 기본 생성자
double gasPedal(double kmh, char type) {
changeGear(type);
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("빵빵");
}
String getCompany() {
return "(주)" + company;
}
static String setCompany(String companyName) {
// System.out.println("자동차 모델 확인: " + model); // 인스턴스 필드 사용 불가
company = companyName;
return company;
}
}
package Week3.staticFolder;
public class Main {
public static void main(String[] args) {
// 클래스 필드 company 확인
System.out.println(Car.company + "\n");
// 클래스 필드 변경 및 확인
Car.company = "Audi";
System.out.println(Car.company + "\n");
// 클래스 메서드 호출
String companyName = Car.setCompany("Benz");
System.out.println("companyName = " + companyName);
System.out.println();
// 참조형 변수 사용
Car car = new Car(); // 객체 생성
car.company = "Ferrari";
System.out.println(car.company + "\n");
String companyName2 = car.setCompany("Lamborghini");
System.out.println("companyName2 = " + companyName2);
}
}
지역 변수란
메서드 내부에 선언한 변수를 의미한다
메서드가 실행될 때마다 독립적인 값을 저장하고 관리한다
지역 변수는 메서드 내부에서 정의 될 때 생성되어
메서드가 종료될 때 까지만 유지된다.
package Week3.sample;
//지역변수
public class Main {
public static void main(String[] args) {
Main main = new Main();
System.out.println(main.getNumber());
System.out.println(main.getNumber());
}
//메서드
public int getNumber(){
//[지역 변수] <=> 전역변수(static)
//해당 메서드가 실행될 때 마다 독립적인 값을 저장하고 관리한다.
//이 지역변수는 메서드 내부에서 정리할 때 생성한다.
//이 메서드가 종료될 때 소멸된다.
int number = 1;
number += 1;
return number;
}
}
//main.getNumber() = 2
//main.getNumber() = 2
//main.getNumber() = 2
// 값이 쌓이며 2,4,6 ... 이되는게 아닌 출력후 삭제되며 2, 2, 2 가 출력되는것이다.
final 필드와 상수
final은 최종 이라는 의미
초기값이 final로 저장되면 해당값을 수정할 수 없다.
final 은 반드시 초기값을 지정해야한다.
필드 타입 앞에 fianl 키워드를 추가하여 fianl 필드를 선언할 수 있다.
final String company = "GENESIS";
...
Car car = new Car ();
System.out.println(car.company); //GENESIS 출력
//car.company = "Benz"; 수정을 요청하면 오류가 발생한다.
상수의 특정
값이 반드시 한개이며 불변의 값을 의미한다.
인스턴스마다 상수를 저장할 필요가 없다.
static final String COMPANY = "GENESIS";
//final 앞에 static 키워드를 추가하여 모든 인스턴스가 공유할 수 있는 값이 한개이며 상수를 선언한다.
//일반적인 상수는 대문자로 작성해야하는 것이 관례이다.
생성자란
객체가 생성될 때 호출되며 객체를 초기화하는 역할을 수행한다.
public Car() {} // 선언
Car car = new car () ; // 호출
//생성자는 반환 타입이 없고, 이름은 클래스의 이름과 동일하다.
//new 연산자에 의해 객체가 생성되며 Car(); 생성자가 호출된다.
기본생성자
선언할 때 괄호() 안에 아무것도 넣지 않는 생성자를 의미한다.
- 모든 클래스는 반드시 생성자가 하나 이상 존재한다.
- 생성자를 선언하지 않아도 기본생성자를 자동으로 추가시켜준다.
- 생성자가 선언되어있다면 컴파일러는 기본생성자를 추가하지않는다.
public class Car{
public Car(String model){ //생성자 선언
}// 생성자가 한개 이상 선언되었기에 기본생성자를 추가하지 않는다.
}
public class Car{
public Car() {} // 생성자를 선언하지 않음
} //컴파일러가 추가시켜준다.
class Car {
Car(){} //컴파일러가 추가시켜준다.
}
필드 초기화
생성자는 객체를 초기화 시켜준다.
객체를 만들 떄 인스턴스마다 다른 값을 가져야 한다면 생성자를 통해 필드를 초기화 할 수 있다.
인스턴스마다 동일한 데이터를 가지는 필드는 초기값을 정해두는 것이 좋다.
public Car(String modelName, Stirng colorName, double priceValue){
model = modelName;
color = colorName;
price = priceValue;
} //생성자가 한개이상 존재한다.
Car car = new Car();
// 컴파일러가 자동 기본 생성자를 추가해주지않아 오류가 발생한다.
생성자 오버로딩
생성자를 통해 필드를 초기화 하면 오버로딩을 적용할 수 있다.
public Car(String modelName, String colorName, double priceValue)
public Car(String colorName, String modelName, double priceValue)
//위처럼 타입이 일치하는데 매개변수명만 다르게해도 오류가 발생한다
//modelName과 colorName 매개변수의 위치가 달라도
//String, Stirng,double :개수 ,타입, 순서가 동일하여 중복이 불가능하다.
this란
자기자신을 표현하는 키워드
// 객체 내부 생성자 및 메서드에서 객체 내부 멤버에 접근하기 위해 사용한다.
// 객체 내부 멤버에 따라 this가 필수는 아니다.(필수가 될 수도 있다)
public Car (String model, String color, double price){
model = model;
color = color;
price = price;
}
//생성자를 선언하는데 매개변수명과 객체의 필드명이 동일하다면
//오류가 발생하지 않지만 가장 가까운 매개변수명을 가리키게된다.
//결국 자기자신에게 값을 대입하는 상황이 된다.
this 키워드를 사용하면 해결이 가능하다.
public Car(String model, String color, double price){
this.model = model;
this.color = color;
this.price = price;
}
// this 키워드를 통해 변수명에 해당하는 객체의 필드에 접근하여
//받아온 매개변수의 매개값을 객체의 필드에 대입하여 저장할 수 있다.
//this는 자기자신을 뜻하므로 객체의 메서드에서 리턴타입이 인스턴스 자신의 클래스타입이라면
//this를 사용하여 인스턴스 자신의 주소를 반환할 수 있다.
// 한마디로
Car returnInstance(){
return this; //<= 결국 Car를 뜻하고 Car가 입력되어 Car가 출력된다.
}
this()
인스턴스 자신의 생성자를 호출하는 키워드이다.
객체 내부 생성자 및 메서드에서 해당 객체의 생성자를 호출하기 위해 사용된다.
생성자를 통해 객체의 필드를 초기화할 때 중복되는 코드를 줄여줄 수 있다.
public Car(String model){
this.model = model;
this.color = "Blue";
this.price = 5000000;
}
public Car(String model, String color){
this.model = model;
this.color = color;
this.price = 5000000;
}
public Car(String model, String color, double price){
this.model = model;
this.color = color;
this.price = price;
}
//생성자를 선언하였을 때 코드중복이 발생한다.
//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;
|
//this()키워드를 사용하여 다른 생성자를 호출할 때
//해당 생성자의 첫 줄에 작성되어야한다.
public Car(String model){
System.out.println("model = " + model);
this(mode, "Blue" ,5000000);
}
//this()키워드로 다른 생성자 호출 이전에 코드가 존재하면 오류가 발생한다.
접근제어자
제어자는 클래스, 변수, 메서드의 선언부에 사용되어 부가적인 의미를 부여한다.
접근제어자 : public, protected, default, private
그 외 제어자 : static, fianal, abstract
하나의 대상에 여러 개의 제어자를 조합해서 사용할 수 있으나
접근제어자는 하나만 사용할 수 있다.
접근제어자는 멤버 or 클래스에 사용하고 외부에서 접근하지 못하도록 제한한다.
클래스, 멤버 변수, 메서드, 사용자에 사용되고 지정되어 있지않다면 default 이다.
- public : 접근 제한이 전혀없다.
- protected : 같은 패키지 내에서, 다른 패키지의 자손클래스에서 접근이가능하다.
- default : 같은 패키지 내에서만 접근이 가능하다.
- private : 같은 클래스 내에서만 접근이 가능하다.
사용가능한 접근 제어자
- 클래스 : public, default
- 메서드 & 멤버 변수 : public, protected, default, private
- 지역변수는 없다.
접근 제어자를 이용한 캡슐화(은닉성)
- 접근제어자는 클래스 내부에 선언된 데이터를 보호하기 위해 사용된다.
- 유효한 값을 유지하도록 함부로 변경하지 못하도록 접근을 제어하는 것이 필요하다.
- Ex) 원래값 int를 String 문자열로 변경을 시도한다 등등
생성자의 접근 제어자
- 생성자에 접근 제어자를 사용함으로 인스턴스의 생성을 제한할 수 있다.
- 일반적 생성자의 접근제어자는 클래스의 접근 제어자와 일치한다.
객체의 무결성, 변경이 없는 상태를 유지하기위해
접근 제어자를 사용한다.
외부에서 필드에 직접 접근하는 것을 막기 위해
필드에 private, default 등 접근제어자를 사용한다.
private의 필드를 읽거나 가져올려면 Getter와 Setter를 사용하면된다.
Getter
외부에서 객체의 private한 필드를 읽어야될 때 Getter 메서드를 사용한다.
private double speed; //자동차 속도, km/h
private char gear = 'P'; //기어의 상태, P, R, N, D
private boolean lights; //자동차 조명의 상태 true, false
//자동차 클래스의 필드에 private 접근 제어자로 지정한 필드가 있을 때
//Getter 메서드를 통해 값을 가져올 수 있다.
public String getModel(){
return model;
}
public String getColor(){
return color;
}
public double getPrice(){
return price;
}
//메서드 이름의 규칙은 : get + 필드이름(첫 글자 대문자)이다.
//사용하는 방법은 인스턴스 메서드 호출과 동일하다.
Setter
외부에서 객체의 private한 필드를 저장/수정할 필요가 있을 때 Setter를 사용한다.
private double speed;
private char gear = 'P';
private boolean lights;
//이처럼 private접근 제어자로 지정한 필드가 있을 경우
// 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;
}
//메서드 이름 규칙 : set + 필드이름 (첫 글자 대문자) 이다.
//사용방법은 인스턴스 메서드 호출과 동일하다.
제어자의 조합
사용 가능한 제어자
- 클래스 : public, default, final, abstract
- 메서드 : public, protected, default, private, final, abstract, static
- 멤버 변수 : public, protected, default, private, final, static
- 지역 변수 : final
- 메서드에 static과 abstract를 같이 사용할 수 없다.
- 클래스에 abstract와 final을 동시 사용할 수 없다
- abstract 메서드의 접근 제어자가 private일 수 없다.
- 메서드에 private와 final을 같이 사용할 필요가 없다.
package와 import
package 란
클래스의 일부분이며 클래스를 식별해 주는 용도이다
패키지는 상위, 하위 패키지를 도트(.)로 구분한다.
package 상위 패키지, 하위 패키지; 이렇게 선언할 수 있다.
import란
다른패키지에 있는 클래스를 사용하기위해 명시하는 키워드
서로 다른 패키지에 있는 같은 이름의 클래스를 동시에 사용하려면
해당 클래스에 패키지 명을 전부 명시해야한다.
상속이란
부모가 자식에게 물려주는 행위
객체 지향 프로그램에서 부모 클래스의 필드와 메서드를 자식클래스에게 물려줄 수 있다.
상속을 사용하면 유지보수가 쉽고 간결해진다.
클래스간의 상속은 extends 키워드를 사용하면된다.
public class 자식클래스 extends 부모클래스 {
//상속키워드는 extends이다. (확장)
}
- 부모 클래스에 새로운 필드가와 메서드가 추가되면 자식클래스는 이를 상속받아 사용할 수 있다.
- 자식 클래스에 새로운 필드와 메서드가 추가되어도 부모 클래스는 어떠한 영향도 받지않는다.
- 따라서 자식 클래스의 멤버 개수는 부모 클래스보다 항상 같거나 많다.
결론 : 고유 필드와 고유데이터를 가진 부모클래스는 고정값에 두면된다.
클래스 간의 관계
상속 관게 ; is -a ("~은 ~(이)다") 현재 진행형
포함 관계 : has - a("~은~을(를)갖고있다") 현재 난 이것을 갖고있다.
단일 상속과 다중상속
Java는 다중상속 개념이 허용되지않는다.
상속이란 하나의 고유데이터로 점점 퍼져나가는 것을 의미하는데.
다중상속이 된다면 용량면 데이터면에서 시작점이 다르고 변경해야할 것이 수무히 많다.
Object = 객체를 의미 = 최상위 부모 클래스이다.
부모클래스가 없는 자식클래스는 자동적으로 Object를 상속받는다
Object clone(): 해당 객체의 복제본을 생성하고 반환한다.
boolean equals(Object object) : 해당 객체와 전달받은 객체를 비교하여 true, false를 출력
Class getClass () : 해당 객체의 클래스 타입을 반환한다.
int hashCode() : 자바에서 객체를 식별하는 정수값 해시코드를 반환한다.
String toString () : 해당 객체의 정보를 문자열로 반환한다.
오버라이딩
부모클래스로 부터 상속받은 메서드 내용을 재정의한다.
고유데이터를 가지고 있지 않고 객체화만 시켜놓은 상태라면
자식 클래스는 자기 입맛대로 인스턴스화 시켜서 출력가능하다.
오버라이딩을 하기 위한 조건들
- 선언부가 부모 클래스의 메서드와 일치해야한다.
- 접근 제어자를 부모 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
- 부모클래스의 메서드 보다 많이 선언할 수 있다.
super와 super()
부모 클래스의 멤버를 참조할 수 있는 키워드이다.
객체 내부생성자 및 메서드에서
부모 클래스의 멤버에 접근하기 위해 사용할 수있다.
자식 클래스 내부에서 선언한 멤버와
부모 클래스에 상속받은 멤버와
이름이 같을 경우 구분하기위해 사용한다.
부모의 정보데이터가 필요한 순간에 사용한다.
//부모 클래스 Car
String model;
Stirng color;
double price;
//자식 클래스 SportsCar
String model = "Ferrari";
String color = "Red";
double price =300000000;
public void setCarInfo(String mode, String color, double price){
super.model = model; //부모 필드에 세팅
super.color = color; //부모 필드에 세팅
this.price = price; //자식 필드 세팅
}
//자식 클래스의 메서드를 호출하면 super키워드로 접근한
// 부모 클래스의 model, color 필드에 매개변수 값이 저장된다.
// this키워드로 접근한 자식 클래스의 price 필드에는 매개변수의 값이 저장된다.
super()는
부모 클래스의 생성자를 호출할 수 있는 키워드이다.
객체 내부 생성자 및 메서드에서
해당 객체의 부모 클래스의 생성자를
호출하기 위해 사용된다.
자식 클래스의 객체가 생성될 때
부모 클래스들이 모두 합쳐져서
하나의 인스턴스가 생성된다.
부모 클래스의 멤버들의 초기화 작업이 먼저 수행되어야한다.
// 자식 클래스의 생성자에서는 부모클래스의 생성자가 호출된다.
// 부모 클래스의 생성자는 가장 첫 줄에서 호출이 되어야한다.
// 부모 클래스 Car 생성자
public Car(String model, String color, double price){
this.model = model;
this.color = color;
this.price = price;
}
//자식 클래스 SprotsCar생성자
public SprortsCar(String model, String color, double pirce){
//this.engine =engine;// 오류가 발생한다.
super(mode, color, price);
this.engine =engine;
}
//자식 클래스 객체를 생성한다면
//생성자 매개변수에 매개 값을 받아와서
// super()를 사용하여 부모 생성자의 매개변수의 매개 값을 전달하여 호출한다
// 부모 클래스의 멤버를 먼저 초기화 한다.
//오버로딩 된 부모 클래스의 생성자가 없다 하더라도
// 부모 클래스의 기본 생성자를 호출해야한다.
다형성이란
여러가지 형태를 가질 수 있는 능력을 의미한다.
소프트웨어 또한 구성하고 있는 객체를 바꿧을 때 소프트웨어의 실행 성능 및 결과물이 다르게 나올 수 있다.
Tire tire = new HakookTire("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"));
//매개변수에도 다형성이 적용될 수 있다.
//Car생성자에서 매개변수의 타입이 부모 타이어 이기에
//자식 타이어 객체들을 매개값으로 전달 할 수 있다.
Tire getHankookTire(){
return new HankookTire("HANKOOK");
}
Tire getKiaTire(){
return new KiaTire("KIA");
}
...
Tire hankookTire = car1,getHankookTire();
KiaTire kiaTire = (KiaTire) car2. getKiaTire();
//반환 타입에도 다형성이 적용될 수 있다.
//반환 타입이 부모 타이어 이기에 자식 타이어 객체들을 반환값으로 지정할 수 있다.
//자동 타입 변환이 된 반환 값인 자식 타이어 객체를 강제 타입 변환 할 수도 있다.
부모타입변수 = 자식타입 객체;를 할경우 자동 타입 변환이 일어난다
자식 객체는 부모객체의 멤버를 상속받기에 부모와 동일하게 취급될 수 있다
하지만 자식객체의 따로 입력된 메서드(입력값)가 부모객체의 메서드로 정의 될 수없다.
고유데이터를 가지고있는 부모객체이기에
고유데이터를 상속받은 자식객체가
일부를 일시적으로 변환시킬 수 는 있어도
자식객체의 정의가
부모객체로 정의될 수는 없다는것
강제 타입 변환
자식 타입 변수 = (자식 타입) 부모 타입 객체;
부모 타입 객체는 자식 타입변수로 자동 타입변환이 되지않는다.
타입 변환 연산자를 사용하여 강제 변환 할 수 있다.
//자식타입객체가 자동 타입 변환된 부모타입의 변수
Mammel mammel = new Whale();
mammal.feeding();
//자식객체 고래의 수영 기능을 사용하고 싶다면
//자식타입으로 강제 타입변환을 하면된다.
Whale whale = (Whale) mammal;
whale.swimming();
//무조건 강제 타입 변환을 할 수있지 않다.
//자식 타입 객체가 부모타입으로 자동 타입변환 된 후 다시 자식타입으로 변환될 때만 강제타입변환이 가능하다.
//부모 타입변수로는 자식타입객체의 고유한 멤버를 사용할 수 없기에 사용이 필요한 경우가 생겼을때
//강제타입변환을 사용한다.
instance of
다형성 기능으로 인해 해당 클래스 객체의 원래 클래스명을 체크하는 명령어.
이 명령어를 통해 해당 객체가 의도하는 클래스의 객체인지 식별이 가능하다.
{대상객체} instace of {클래스 이름} <= 사용하면 응답값은 boolean이다.
package Week3.instanceofSample;
// 다형성
class Parent { }
class Child extends Parent { }
class Brother extends Parent { }
public class Main {
public static void main(String[] args) {
// Parent pc = new Child(); // 다형성 허용 (자식 -> 부모)
Parent p = new Parent();
System.out.println(p instanceof Object); // true 출력
System.out.println(p instanceof Parent); // true 출력
System.out.println(p instanceof Child); // false 출력
Parent c = new Child();
System.out.println(c instanceof Object); // true 출력
System.out.println(c instanceof Parent); // true 출력
System.out.println(c instanceof Child); // true 출력
}
}
추상 클래스란
클래스가 설계도라면 추상 클래스는 미완성된 설계도이다.
public abstract class 추상클래스 명 { }
//추상 클래스는 추상 메서드를 포함할 수 있다.
//추상 메서드가 없어도 추상 클래스로 선언이 가능하다.
//추상 클래스는 자식 클래스에 상속되어 자식 클래스에 의해서만 완성될 수 있다.
//추상 클래스는 여러개의 자식 클래스들에서 공통적인 필드나 메서드를 추출해서 만들 수 있다.
//추상클래스는 완벽하지 않은 설계도 이기에 고유데이터가 정해져있지않아 자식클래스에서 다양한용도로 사용이 가능하다.
public abstract class 추상클래스명 {
abstract 리턴타입 메서드이름 (매개변수, ...);
}
추상 메서드는 일반 메서드와 다르게 블록{} 이 없다. (정의만한다)
// 추상 메서드는 extends(상속) 키워드를 사용하여 클래스에서 상속된다.
public class 클래스명 extends 추상클래스명 {
@Override
pubic 리턴타입 메서드이름 (매개변수, ...){
//실행문
}
}
//상속받은 클래스에서 추상 클래스의 추상 메서드는 반드시 오버라이딩 되어야한다.
//추상이란 의미에 맞게 추상클래스를 상속받았으면 정의를 해야 사용이 가능하다.
package Week3.abs;
//추상 클래스 Car
public abstract class Car {
double speed;
public double gasPedal(double kmh){
speed = kmh;
return speed;
}
public double brakePedal(){
speed = 0;
return speed;
}
public abstract void horn ();
}
package Week3.abs;
public class AudiCar extends Car {
@Override
public void horn(){
System.out.println("Audi 빵빵");
}
}
package Week3.abs;
public class BenzCar extends Car {
@Override
public void horn(){
System.out.println("Benz 빵빵");
}
}
package Week3.abs;
public class ZenesisCar extends Car {
@Override
public void horn(){
System.out.println("Zenesis 빵빵");
}
}
package Week3.abs;
public class Main {
public static void main(String[] args) {
Car car1 = new BenzCar();
car1.horn();
System.out.println();
Car car2 = new AudiCar();
car2.horn();
System.out.println();
Car car3 = new ZenesisCar();
car3.horn();
System.out.println();
}
}
//BenzCar, AudiCar, ZenesisCar는 horn()메서드 내용에 차이가 존재한다.
//horn()메서드를 추상 메서드로 선언하여 자식 클래스에서 재정의 될 수 있게 한다.
인터페이스
역할
- 두 객체를 연결해 주는 다리역할을 해준다.
- 상속 관계가 없는 다른 클래스들이 서로 동일한 메서드를 구현해야 할 때
- 인터페이스는 구현클래스들의 동일한 사용 방법과 행위를 보장해준다.
- 인터페이스는 스팩이 정의된 메서드들의 집합이다.
- 인터페이스의 구현 클래스들은 반드시 정의된 메서드들을 구현해야한다.
- 구현 클래스들의 동일한 사용방법과 행위를 보장해 줄 수 있다.
- 이러한 특징들이 인터페이스에 다형성을 적용할 수 있게 한다.
//인터페이스 선언
public interface 인터페이스명 {
}
//인터페이스는 클래스와 마찬가지로 public,default접근제어자를 지정할 수 있다.
//인터페이스의 모든 멤버 변수는 public static final이어야한다.(생략 가능)
// 인터페이스의 모든 메서드는 public abstract이어야한다.(생략가능)
//생략되는 제어자는 컴파일러가 자동으로 추가해준다.
public interface 인터페이스명{
public static final char A = 'A';
static char B = 'B';
final char C = 'C';
char D = 'D'
void turnOn() ;
}
//인터페이스는 추상 클래스와 마찬가지로 직접 인스턴스를 생설할 수 없기에 클래스에 구현되어 생성된다.
public class 클래스명 implements 인터페이스명{
//추상 메서드 오버라이딩
@Override
public 리턴타입 메서드이름 (매개변수 , . .. ){
//실행문
}
}
//인터페이스의 추상 메서드는 구현될 때 반드시 오바라이딩이 되어야한다.
//인터페이스의 추상 메서드 일부만 구현해야한다면 해당 클래스를 추상 클래스로 변경해주면된다(abstract)
//인터페이스간 상속도 가능하다.
//implements가 아닌 extends를 사용한다
//인터페이스는 다중 상속이 가능하다.
package Week3.interSample;
public class Main {
public static void main(String[] args) {
// A 인터페이스에 구현체 B 대입
A a1 = new B();
a1.a();
//a1은 인터페이스 A타입(자동 형변환) 이기 때문에, a() 메서드만 가질 수 있다.
// a1.b(); // 불가능
System.out.println("\nB 강제 타입변환");
B b = (B) a1;
b.a();
b.b(); // 강제 타입변환으로 사용 가능
System.out.println();
// A 인터페이스에 구편체 B를 상속받은 C 대입
A a2 = new C();
a2.a();
//a2.b(); // 불가능
//a2.c(); // 불가능
System.out.println("\nC 강제 타입변환");
C c = (C) a2;
c.a();
c.b(); // 강제 타입변환으로 사용 가능
c.c(); // 강제 타입변환으로 사용 가능
}
}
interface A {
void a();
}
class B implements A {
@Override
public void a() {
System.out.println("B.a()");
}
public void b() {
System.out.println("B.b()");
}
}
class C extends B {
public void c() {
System.out.println("C.c()");
}
}
디폴트 메서드
디폴트 메서드는 추상 메서드의 기본적인 구현을 제공하는 메서드이다.
// 메서드 앞에 default 키워드를 붙이며 블럭{} 이 존재해야한다.
// default 메서드 접근 제어자가 public 이며 생략이 가능하다.
// 추상 메서드가 아니기에 인터페이스의 구현체들에서 필수로 재정의 할 필요는 없다.
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");
}
}
// void a() 기본값을 미리 정의해두어 클래스 생성시 기본값으로 미리 할당을 해놓은 상태이다.
인터페이스에서 static 메서드 선언이 가능하다.
//static(공공의) 특성 그대로 인터페이스의 static 메서드 또한 객체없이 호출이 가능하다.
//선언 방법과 호출방법은 클래스의 static 메서드와 동일하다. (생략하면 컴파일러가 public을 추가해준다.)
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");
}
}
다형성
//자동 타입 변환
//인터페이스 변수 = 구현객체; 는 자동으로 타입 변환이 일어난다
public class Main{
public static void main(String[] args){
//A 인터페이스에 구현체 B대입
A a1 = new B():
// A인터페이스에 구현체 B를 상속받은 C대입
}
}
interface A{ }
class B implements A {}
class C extends B
//강제 타입변환
//구현 객체 타입 변수 = (구현 객체 타입) 인터페이스 변수;
public class Main{
public static void main(String[] agrs){
//A인터페이스 구현체 B대입
A a1 = new B();
a1.a();
//a1.b();는 불가능하다.
System.out.println("\nB 강제 타입변환");
B b = (B) a1;
b.a();
b.b(); //강제 타입변환으로 사용이 가능하다.
}
}
package Week3.interExample1;
public class Main {
public static void main(String[] args) {
//A인터페이스에 구현체 B 대입
A a1 = new B();
a1.a();
// a1.b(); 불가능하다.
System.out.println("\nB 강제 타입변환");
B b =(B) a1;
b.a();
b.b(); //강제타입변환하여 사용이가능하다.
System.out.println();
//A 인터페이스에 구현체 B를 상속받은 C대입
A a2 = new C();
a2.a();
// a2.b();
// a2.c();
System.out.println("\nC 강제타입변환");
C c= (C) a2;
c.a();
c.b();
c.c();
}
}
interface A {
void a();
}
class B implements A{
@Override
public void a() {
System.out.println("B.a()");
}
public void b(){
System.out.println("B.b()");
}
}
class C extends B{
public void c(){
System.out.println("C.c()");
}
}
package Week3.inter;
public interface MultiRemoteController {
void turnOnOff();
void channelUp();
void channelDown();
void volumeUp();
void volumeDown();
// 매개변수와 반환타입 다형성 확인 메서드
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 없음");
}
}
}
package Week3.inter;
public abstract class Tv {
private String company; // 티비 회사
private int channel = 1; // 현재 채널 상태
private int volume = 0; // 현재 볼륨 상태
private boolean power = false; // 현재 전원 상태
public Tv(String company) {
this.company = company;
}
public void displayPower(String company, boolean power) {
if(power) {
System.out.println(company + " Tv 전원이 켜졌습니다.");
} else {
System.out.println(company + " Tv 전원이 종료되었습니다.");
}
}
public void displayChannel(int channel) {
System.out.println("현재 채널은 " + channel);
}
public void displayVolume(int volume) {
System.out.println("현재 볼륨은 " + volume);
}
public String getCompany() {
return company;
}
public int getChannel() {
return channel;
}
public int getVolume() {
return volume;
}
public boolean isPower() {
return power;
}
public void setChannel(int channel) {
this.channel = Math.max(channel, 0);
}
public void setVolume(int volume) {
this.volume = Math.max(volume, 0);
}
public void setPower(boolean power) {
this.power = power;
}
}
package Week3.inter;
public class LgTv extends Tv implements MultiRemoteController {
public LgTv(String company) {
super(company);
}
@Override
public void turnOnOff() {
setPower(!isPower());
displayPower(getCompany(), isPower());
}
@Override
public void channelUp() {
setChannel(getChannel() + 1);
displayChannel(getChannel());
}
@Override
public void channelDown() {
setChannel(getChannel() - 1);
displayChannel(getChannel());
}
@Override
public void volumeUp() {
setVolume(getVolume() + 1);
displayVolume(getVolume());
}
@Override
public void volumeDown() {
setVolume(getVolume() - 1);
displayVolume(getVolume());
}
}
package Week3.inter;
public class SamsungTv extends Tv implements MultiRemoteController{
public SamsungTv(String company) {
super(company);
}
@Override
public void turnOnOff() {
setPower(!isPower());
displayPower(getCompany(), isPower());
}
@Override
public void channelUp() {
setChannel(getChannel() + 1);
displayChannel(getChannel());
}
@Override
public void channelDown() {
setChannel(getChannel() - 1);
displayChannel(getChannel());
}
@Override
public void volumeUp() {
setVolume(getVolume() + 1);
displayVolume(getVolume());
}
@Override
public void volumeDown() {
setVolume(getVolume() - 1);
displayVolume(getVolume());
}
}
package Week3.inter;
public class Main {
public static void main(String[] args) {
// LG TV 구현체를 조작
// 자동 형 변환
MultiRemoteController mrc = new LgTv("LG");
mrc.turnOnOff();
mrc.volumeUp();
mrc.channelDown();
mrc.channelUp();
mrc.turnOnOff();
// 조작 대상을 Samsung TV로 교체
System.out.println("\n<Samsung TV로 교체>");
mrc = new SamsungTv("Samsung");
mrc.turnOnOff();
mrc.channelUp();
mrc.volumeDown();
mrc.volumeUp();
mrc.turnOnOff();
// 매개변수, 반환타입 다형성 체크
System.out.println("\n<매개변수, 반환타입 다형성 체크>");
MultiRemoteController samsung = mrc.getTV(new SamsungTv("Samsung"));
samsung.turnOnOff();
SamsungTv samsungTv = (SamsungTv) samsung;
samsungTv.turnOnOff();
System.out.println();
MultiRemoteController lg = mrc.getTV(new LgTv("LG"));
lg.turnOnOff();
LgTv lgTv = (LgTv) lg;
lgTv.turnOnOff();
}
}
'Java' 카테고리의 다른 글
스파르타 코딩클럽 부트캠프 (Java 문법 5장) (0) | 2024.05.03 |
---|---|
스파르타 코딩클럽 부트캠프 (Java 문법 4장) (1) | 2024.05.02 |
스파르타 코딩클럽 자바문법 2장 배열, 컬렉션정리 (1) | 2024.04.25 |
스파르타 코딩클럽 부트캠프 (Java 문법 2장) (0) | 2024.04.24 |
스파르타 코딩클럽 부트캠프 (Java 문법 1장) (2) | 2024.04.22 |