객체
- 우리가 생각할 수 있는 어떤 사물이나 동물
ex) 컴퓨터, 모닡, 키보드, 마우스, 책, 선풍기, 가방... 등- 클래스로부터 만들어지는 것
객체지향 프로그래밍
객체들끼리 서로 어우러진 형태로 프로그램을 구성
만든 이유 : 4개의 서로 다른 데이터를 한꺼번에 관리하고자 만듦
String modelName2 = "하양이";
String resolution2 = "UHD";
int price2 = 300000;
String color2 = "화이트";
BlackBox bbox = new BlackBox();
클래스
- 예를 들어 설명서나 설계도 같은 거
- 설계도를 클래스로 보면 되고 객체는 그 설계도로부터 만들어진 어떤 결과물이라 생각
블랙박스라는 클래스는 이렇게 정의하는 것을 인스턴스 변수라고 한다.
public class BlackBox{
String modelName;
String resolution;
int price;
String color;
}
-> 4개의 인스턴스 변수를 가지게 되는 것이다.
밑에서 블랙박스 객체를 만듦
b1.modelName = "까망이";
...
매개변수, 파라미터의 타입이 다르거나 또는 개수가 다르면 method of loading이 가능하다.
-> 레코드 위에 있는 메소드를 호출해주면 된다.
(레코드라는 메소드를 호출하는데 거기에다가 기본 값으로 true, showDateTime/showSpeed은 true, minute 정보는 5라고 넣어주면 이 레코드라는 메소드가 호출될 때 여기 내에서는 또
위에 있는 record라는 메소드를 다시 새롭게 호출하면서 여기의 동작을 가지고 위에서 적었는 print문 4줄에 해당하는 것을 똑같이 해줄 수 있다.
-> 레코드라는 메소드를 똑같은 동작을 2번 정의하지 않고 새롭게 메소드를 호출하는데 그때 값만 기본적으로 정의된 값을 던져주는 거고 그러면 이 객체를 통해서 메소드를 호출할 때는 아무 값을 몰라도 그냥 비워둔 채로 호출하게 되면 기본적인 값을 통해서 동작을 하게 된다.
클래스 메소드를 사용할 때는 메소드 내에서 인스턴스 변수의 사용이 필요없는 경우에 공통적으로 적용되는 기능을 클래스 메소드를 사용해 볼 수 있을 것이다.
String s = String.valueOf(3);
ctrl 누르고 valueOf누르면 알려줌
String 앞에 static이 있다. -> 클래스 메소드로 정의됨.
valueOf라는 메소드는 결국 그냥 전달값으로 받은 이 i값만 가지고 어떤 처리를 하고 나서 반환을 해주는 것이다.
-> 그러니까 string클래스 내에서 어떤 정의되어 있는 인스턴스 변수는 상관없이 전달받은 값 하나만 가지고 처리를 하고 결과를 내뱉어 준다.
이런 경우에 인스턴스 메소드 대신에 클래스 메소드의 사용을 고려해 볼 수 있다.
- 일반적으로 만드는 메소드가 인스턴스 메소드이고 각 개체마다 서로 다른 동작을 하게 되고, static 키워드가 붙은 것은 클래스 메소드이다.
- 개체가 만들어지지 않고도 클래스 이름 점 그리고 이 메소드 이름으로 바로 접근해 볼 수 있다.
-> 이 둘의 차이를 알아야 한다
-> 위 코드는 모델명을 추가하는 메소드다. 여기로 전달되는 model name을 원래 가지고 있는 modelName에 추가하면 알아보기가 더 편하다.
메소드 보기
appendModelName 부분에 컨트롤 클릭하면 메소드로 바로 이동할 수 있고 아니면 이걸 클릭하고 ctrl+shift+i 누르면 이 메소드가 어떻게 생겼는지 볼 수 있다.modelName += modelName;
- 앞에 있는 것은 클래스 인스턴스 변수로 만들어진 모델네임이고 뒤에 있는 모델네임은 전달값으로 전달받은 모델네임을 뜻한다.
-> 이렇게만 두면 지금 메소드 내에서는 모델네임(앞)에다가 모델네임(뒤)을 다시 한번 더하는 즉, 최신형+최신형은 이라고 하고 끝나게 된다. 그러니까 인스턴스 변수 모델네임이 아니고 그냥 전달받은 파라미터 값을 한 번 더 업데이트를 하고 끝나게 된다.- 모델네임(앞)을 파라미터가 아니고 이름이 똑같은 경우에는 클래스가 가지고 있는 인스턴스 변수의 모델네임을 명시하고 싶으면 앞에다가 this. 을 붙여주면 된다.
-> this. 을 붙여주면 클래스의 인스턴스 변수에 직접 바로 접근할 수 있게된다.
-> this.modelName(앞) : 클래스 인스턴스 변수
modelName(뒤) : 파라미터로 전달받은 모델네임
※인스턴스 변수하고 전달받은 파라미터의 변수이름이 똑같다면 앞에 this. 을 꼭 붙여줘야 한다!!!
생성자 : 객체가 만들어질 떄 자동으로 호출되는 메소드
생성자를 만드는 방법
클래스명과 똑같이 적어주면 된다.
생성자를 따로 정의를 해 가지고 한 번에 값을 바로 전달 받고, 그 값들을 인스턴스 변수에다가 직접 넣거나 또 다른 초기 작업을 생성자 내에서 할 수 있다. 그러면 객체를 만들 때마다 매번 인스턴스 변수에다가 값을 넣어주는 작업을 밑에서는 그냥 한 줄로 내 처리를 할 수 있다.BlackBox b2 = new BlackBox("하양이", "UHD", 300000, "화이트");
기본 생성자
-> 처음으로 객체가 만들어질 때는 카운터 값이 0이었을 거니까 0에다가 ++해줘서 1이 들어간다. 그 다음에 새로운 객체가 만들어질 때는 카운터 값은 인스턴스 변수가 아니가 때문에 지금 1로 업데이터 되어 있는 상태인 거고 이거는 모든 객체에서 다 똑같이 공통적으로 사용되는 값이다. 그래서 1이었던 값이 2로 될 거고 또 새로운 기체를 만들면 3이 될 거고 그렇게 업데이트가 된다.
생성자2
this()
기본 생성자를 바로 접근. 기본 생성자의 동작을 그대로 수행하고 나서 아래쪽에 있는 생성자2의 동작을 하게 된다.
요약
생성자는 개체가 만들어질 때 자동으로 호출이 되는 부분.
기본적인 동작이 되는 부분이 있다고 하면 생성자에 명시를 해주면 되고 또는 개체가 생성됨과 동시에 우리가 전달하는 값으로 초기화를 하고자 할 때에도 생성자를 활용할 수가 있다. 그리고 생성자 간에도 서로를 호출하기 위해서는 this()를 활용할 수 있다.
Getter : 값을 가지고 오는 메소드
Setter : 값을 설정하는 메소드
만약 모델네임을 가져오는 메소드라면(Getter),
(Setter)
요약
getter와 setter를 이용하게 되면 어떤 이상한 값이 들어간다던지 값 설정하다가 발생할 수 있는 오류를 줄일 수 있고 또 값을 가져오는 과정에서도 그 값이 없다거나 이상하다거나 할 때 대안으로 줄 수 있는 값을 설정할 수가 있다.
접근 제어자
private : 해당 클래스 내에서만 접근 가능
public : 모든 클래스에서 접근 가능
default : (아무것도 적지 않았을 때) 같은 패키지 내에서만 접근 가능
protected : 같은 패키지 내에서, 다른 패키지인 경우 자식 클래스에서 접근 가능
BlackBox를 Ctrl C + Ctrl R
위쪽에 뭐가 뜨는데 첫번째 부분에 붙여넣기를 하면 BlackBox라는 문구를 찾는다. 두번째 부분에 BlackBoxRefurbish를 치면, 위에 있는 소스코드에서 위에 있는 문구를 모두 찾아가지고 아래 문구로 한번에 바꿔달라는 의미가 된다. esc 누르면 창 닫힘
BlackBox -> BlackBoxRefurbish로 바꿈
※ public은 어디서든지 접근 가능하다.
※ Default는 같은 패키지 내에서만 접근이 가능하다.
- 클래스에도 public을 붙이던지 또는 아무것도 붙이지 않은 디폴트 클래스일지를 통해 가지고 다른 패키지에서 접근 가능할 지 여부를 설정할 수 있다.
- 참고로 java 파일 내에서는 클래스를 여러 개 정의할 수 있다.
-> 하지만 퍼블릭 클래스로 정의를 하게 되는 경우에는 반드시 java 파일명하고 똑같아야 된다.
캡슐화(Encapsulation)
- 서로 관련 있는 데이터 즉 변수 그리고 서로 관련 있는 기능들, 메소드를 블랙박스와 관련된 만큼만의 하나의 클래스로 정의하는 것
정보은닉(Information hiding)
- 정보를 숨기는 것
- 객체 내에 있는 어떤 변수나 메소드의 직접적인 접근을 막고 객체에서 허용해주는 형태로만 허용하는 메소드를 통해서만 접근이 가능하게 하는 것
-> 캡슐화, 정보은닉을 할 수 있게 해주는 게 접근 제어자, 주로 private을 통해 가지고 외부에서 접근을 못하도록 하는 거고 Getter와 Setter를 통해 가지고 어느 정도까지만 허용해가지고 사람들이 그걸 사용할 수 있도록 해주는 것이다.
import chap_07.BlackBoxRefurbish
-> chapter_07에 있는(다른 패키지에 있는) BlackBoxRefurbish이라는 클래스를 사용하겠다는 의미
※위 코드가 없으면 바로 에러 발생
import chap_07.*;
-> 챕터 07에 있는 모든 클래스를 갖다 쓰겠다는 의미
Random Class
- 랜덤 클래스를 이용하면 어떤 값을 랜덤으로 뽑을 수 있게 된다.
- 랜덤 클래스를 쓰기 위해서는 대문자 R로 시작하는 랜덤 객체를 만들면 된다.
- 패키지 아래에 이 코드를 써줘야 Random 클래스를 쓸 수 있다.
- 쓰는 방법은 객체 이름을 랜덤으로 적어준다.
Random random = new Random();
Camera code
- 기본적으로 사진을 촬영할 수 있고 또 동영상을 녹화할 수 있는 기본적인 동작을 수행
SpeedCam code_과속 단속 카메라
- 속도를 체크해서 만약 이 차가 과속이다라고 하면은 차량의 번호를 인식해 가지고 과태료를 부과하는 작업 추가
FactoryCam code_공장 카메라
- 화재 감지 기능 추가
- 화재 감지를 해 자동으로 119에 신고
-> 위 3개의 객체 생성
상속 쓰는 이유
- 기본적인 카메라 모듈에서 제공해주는 Take Picture, Record Video 라는 메소드는 카메라의 것을 그대로 갖다 쓴다.
- 공장 카메라에서 두 메소드는 카메라에 있는 것을 그대로 갖다 쓰고 추가적으로 화재 감지하는 기능만 따로 정의를 할 수 있다.
- 과속 단속 카메라 같은 경우에도 그대로 쓰고 속도 체크하는 부분과 번호 인식하는 기능만 추가해가지고 카메라를 만들면 더 편할 것이다.
-> 그러면 문제가 생겼을 때 또는 수정이 필요할 때도 카메라 내에서 한쪽만 수정을 하게 되면 factoryCam과 SpeedCam도 여기 있는 기능을 그대로 쓰기 때문에 함께 수정사항이 적용되는 효과를 볼 수 있다.
이럴 때 사용하는 것이 바로 상속이다.
상속 하기 위해서는??
- 상속 관계에서 기능을 물려주는 입장이 되는 클래스가 부모 클래스이다. 그리고 이 기능들을 물려받는 클래스가 자식 클래스이다.
- 카메라 : 부모 클래스
- 팩토리 캠과 스피드 캠은 이 카메라의 기능을 그대로 이어받아서 쓰게 되는 자식 클래스가 된다.
- 팩토리 캠과 스피드 캠에서 카메라를 상속하기 위해서는 클래스 명 팩토리 캠 뒤에다가 한 칸 띄우고 extends하고 나서 부모 클래스를 적어주면 된다.
- 부모 클래스 이름인 카메라를 적게 되면 이 카메라로부터 상속을 하게 된 것이다.
※참고로 상속은 한 부모로부터만, 하나의 부모 클래스로부터만 가능하다
SpeedCam code
@Override // annotation
- 부모 클래스에 이런 메소드가 없다면 오버라이딩 대상이 되는 메소드가 없으면 에러를 내뱉어 주는 것이다.
Camera[] cameras = new Camera[3]; cameras[0] = new Camera(); cameras[1] = new FactoryCam(); cameras[2] = new SpeedCam(); for(Camera cam : cameras){ cam.showMainFeature(); }
-> 카메라라는 이름으로 배열을 만들었고 서로 다른 형태의 개체를 집어넣음으로써 반복문을 통해서 우리는 그냥 ShowMainFeature 메소드를 한번 호출함으로써 위에서 했던 동작을 똑같이 할 수 있게된다.
※ SpeedCam speedCam = new SpeedCam();과 같이 생성된 객체도 cameras 배열로 관리는 할 수 있다.
->> 즉, 부모 클래스를 먼저 앞에 적어 줌으로써 부모 클래스 개체 이름은 New 부모 클래스 또는 자식 클래스 이렇게 개체를 만들 수 있다.
((FactoryCam) factoryCam).detectFire();
-> FactoryCam(뒤) 객체는 FactoryCam(앞)이라는 클래스로 형변환이 된 것이다.
※ 공장 카메라에서 제공해주는 클래스를 ㅡㅆ기 위해서는 이런 식으로 형변환을 해야 한다.위처럼 해주면 형변환된 상태에서 각각의 객체가 가지는 주요 기능들을 써볼 수 있다.
instanceof를 통해서 객체가 이 클래스의 인스턴스 인지 여부를 확인하고 그렇다고 할 때는 형 변환을 통해 가지고 클래스의 메소드에 접근할 수 있다.
앞에서 상속을 한 이유
부모 클래스에 있는 변수나 모든 메소드 동작을 자식 클래스에서 그대로 사용하기 위해서 또 공통적인 부분을 사용을 하고 추가적인 부분만 자식 클래스에서 만들어 쓰기 위해서 상속을 했었는데 지금은 부모 클래스에 있는 recordVideo 또 takePicture를 다시 만들게 된 것이다.
-> 상속을 하는 의미가 사라질 수도 있다.
왜냐하면 부모 클래스에서 takePicture의 동작을 바꾼다던지 추가를 하게 되면 speedCam이나 factoryCam의 자식 클래스에서도 똑같이 바꿔줘야 되는 일이 생기기 때문
->이럴때 사용하는 것이 Super이다.
super.recordVideo //부모 클래스에 있음
메소드를 호출 해주면 끝!!
factoryCam의 recordVideo라는 메소드가 호출되고 나면 먼저 super.recordVideo라는 동작을 수행하고 나서 추가로 자식 클래스에서 제공하는 화재 감지 기능을 함께 수행하게 되는 것이다.
자식 클래스에서 오버라이딩을 하긴 했지만 그렇다고 해서 부모 클래스에 정의되어 있는 메소드를 완전히 뒤바꾸는 것이 아니다. 부모 클래스에 있는 내용을 그대로 쓰면서 거기 뒤에서 추가적인 기능을 사용하겠다고 명시를 해주는 것이다.
-> 부모 클래스에서 recordVideo라는 메소드의 동작을 바꾼다고 해도 자식 클래스에서는 따로 해줄 거 없이 바로 부모 클래스의 이 메소드만 호출해주면 변경된 내용이 바로 적용된다.
-> 따로 값을 지정하지 않아도 0이나 0.0과 같은 기본값을 항상 가지게 된다. 메소드가 없다. 모두 소문자로 시작
-> 값을 따로 지정하지 않으면 모두 NULL로 들어간다. 메소드를 가질 수 있다. 모두 대문자로 시작
※ 중요하니까 꼭 이해하기!!
-> 어떤 클래스의 변수를 한 번 더 정해진 값으로 고정하고 싶을 때는 파이널 키워드를 이용할 수 있다.
-> 메소드 오버라이딩을 통해 가지고 멋진 슬로우모드 비디오를 만듦
public final void makeVideo
makeVideo라는 메소드는 자식 클래스에서는 오버라이딩을 할 수가 없게 된다.
- 메소드는 절대 변경하지 말고 무조건 이걸 써야 하는 경우에는 final 키워드를 넣어 줄 수 있다.
- 앞에 public final class를 넣으면 이제 이 클래스를 아예 상속할 수 없게 된다.
정의하는 방법
enum 열거형 이름
Q. 클래스를 이용하여 햄버거를 자동으로 만드는 프로그램을 작성
조건