[객체지향프로그래밍]
OOP(Object Oriented Programming)언어의 특징
- 캡슐화(Encapsulation)
: 정보(멤버변수=인스턴스변수-명사)와 기능(메소드-동사)을 하나로!
- 정보은닉(Information hiding) : private
- 상속(Inheritance)
: 기존에 만들어 놓은 클래스!를 기능을 확장하는 개념
-★다형성(Polymorphysm)
: 클래스에 속해 있는 하나의 메소드가 다양하게 구현, 동작하는 개념. 실제로 가장 어렵고 중요함
- 추상화(Abstrction)
: 실세계에 존재하는 물체(Object)로부터 프로그래밍에 필요한 정보와 기능을 추출해서 프로그래밍화 하는 것.
추상화-캡슐화-정보은닉 연결됨
<면접일화> 볼펜을 주고 객체화해라!
질문의 의미가 궁금하다면 ↓
질문의 의미:
볼펜을 보고 명사적인 모습(심의 굵기, 색, 상표), 동사적인 모습(글을 쓸 수 있는 기능)으로 객체화할 수 있느냐를 물어보는 것
[캡슐화]
VO(Value Object) 클래스
Friend라는 class에 Private String name; private String phone; private int age; 라는 멤버 변수가 들어있는 것이다.
핸드폰 번호를 의미하는 phone의 데이터타입을 int형으로 하지않고 String으로 한 이유로는 int는 연산을 할 때 사용하기 때문이다.
하나의 파일 안에 이름이 다른 두개의 클래스 가능
주의! public이라 하는 접근지정자는 main 메소드가 있는 클래스만 가질 수 있다.
public static void main(String[] args)에서 String name = "홍길동"은 지역 변수이다.
위에서 오류가 일어난 이유는 클래스 Friend의 public이었던 멤버변수가 private으로 바뀌었기 때문!
▷앞의 도형의 모양과 색으로도 접급지정자를 알 수 있다.
사용할 수 있는 메소드명 : 데이터타입 - 클래스명
디폴트(Package): 삼각형, 접근지정가가 붙어 있지 않다.
빨간 private
초록 public
메소드를 호출할 때 public만 뜬다. 여기에 빨간 색인 private이 뜨지 않는다.
우리 멤버일 경우에는 private을 의미하는 빨간네모상자도 나오지만 외부의 경우에는 private을 의미하는 빨간네모상자를 볼 수 없다.
▶ 그렇다면 사용하고자 하는 클래스 안의 접근지정자가 private인 멤버변수는 어떻게 사용하는가?
바로 setter와 getter를 이용해 접근지정자가 private인 멤버변수를 사용할 수 있다.
[setter와 getter의 개념]
setter와 getter를 사용하기 전, 일단 우리가 왜 setter, getter를 사용하려했는지 생각해보는 것이 중요하다.
setter와 getter를 사용하는 이유는! 클래스 안의 private 접근지정자를 가지고 있는 멤버변수에 접근하기 위해서이다.
-setter : 우리, 내 클래스의 멤버변수에 접근할 수 있음, 데이터를 집어넣는 역할
public void setName(String n) {
name = n;
}
==> name은 클래스 Friend의 멤버변수이고 n은 public void setName의 지역변수이다. setter는 외부의 값은 집어넣는 역할을 하므로 name = n;는 외부의 값인 지역변수 n을 name으로 집어넣는다, 대입한다는 뜻이다.
-getter : 데이터를 꺼내가도록 하는 역할
public int getEng() {
return eng;
}
정보를 넣을 땐 setter를, 그 정보, 값을 출력할 때는 getter를 이용해 출력한다.
★getter로 return 이해하기.
setter를 통해 지역변수를 우리멤버 name에 대입한 상황!
main 메소드에소 f.getName()을 출력하려하는 상황으로 Friend의 메소드 getName()을 호출!
호출된 메소드 getName()는 return값이 name을 들고 호출되어진다.
클래스의 멤버변수에 접근지정자 private을 사용하는 순간 더 이상 f.name의 형식으로 사용할 수 없다. 그렇기 때문에 setter와 getter를 통해 값을 대입하고 출력한다. 기존의 f.name에 오류가 뜨는 이유도 그러하다. 왼쪽과 같이 하면 오류, 오른쪽처럼 정상적으로 작동한다.
f.setName을 예로 들자면 f.setName의 괄호( ) 안에 들어가는 지역변수가 class Friend의 메소드 setName을 통해 멤버변수 private String name;을 사용할 수 있게 해주는 것이다. f.setName의 괄호( ) 안에 대입하고 싶은 지역변수를 넣으면 class Friend의 멤버변수 name에 지역변수의 값을 대입! 그 값을 출력하고 싶다면 getName을 사용! getter는 그 값을 가지고 되돌아가기 때문.
클래스를 이용하기 위해 만든 객체생성한 변수.set우리멤버변수
ex) f.setName("홍길동");과 같이 해야 한다.
p에서 오류가 난 이유는 setName을 복붙해왔기때문에 () 안에 String n이 들어가 있어서! 원래는 String p가 들어가야함.
p오류 제거된 것!
setter는 외부에서 전달받는 데이터(지역변수 n)를 우리멤버 name에게 집어넣으려고 하는 것!
우리멤버라는 것을 명확하게 알려주기 위해 this 라는 키워드를 사용함.
우리멤버와 지역변수가 명확하게 구분될 경우는 사용할 필요가 없음.
setter에서 class Friend의 멤버변수 중 하나인 name은 우리멤버, n은 지역변수
setter에 입력한 값이 getter로 호출되어 출력되는 것을 확인할 수 있다.
★헷갈리니까 한번 더!
▶setter의 경우: public void set클래스의 멤버변수명(타입명 지역변수)
public void setName(String n){
name = n;
}
▶getter의 경우: public 타입명 get클래스의 멤버변수명(){return 멤버변수명;}
public String getName(){
return name;
}
위에서 보다시피 f.setName("홍길동");은 Friend의 setter로 가서 값이 넣어진다.
그 값을 꺼낼 때는 f.getName()과 같이 getter를 이용해 꺼낸다.
setter와 getter를 직접 입력할 때 데이터타입 주의!
★값을 입력할 때는 setter를, 출력할 떄는 getter를 사용한다.
--> 총 과정에 대해 정리하자면 ①class Friend에서 private인 멤버변수를 사용하기 위해 setter와 getter를 이용하고 ②메인 메소드에서 class Friend를 사용하기 위해 class Friend의 객체를 생성한 뒤 ③그곳에 f.setName("홍길동");과 같이 객체와 setter를 이용해 데이터를 집어넣고(대입), ④같은 방식으로 객체 getter를 이용해 출력한다.
★setter의 용도: 수정 + 데이터를 집어넣기
[성적 클래스]
점수를 연산해야하기 때문에 멤버변수 타입에 int가 있는 것을 확인할 수 있다.
위처럼 클래스, 멤버변수, setter, gertter 잘 만들어놓고 내가 실수하는 것은?
-> 바로 클래스 객체 생성 잘하고 메소드 호출시 setName를 이용해 데이터를 집어넣지 않는다는 것이다!
-> 대입은 setter, 값을 호출해 출력할 때는 getter라는 것 잊지말기!
★setter의 용도는 수정 + 데이터를 집어넣기
성적이 잘못입력한 경우, 국어점수만 바뀌었어도 우리멤버끼리는 막 접근해 수정할 수 있다는 것!
BUT! getter를 이용해 하나씩 하나씩 값을 출력을 하다보니 너무 귀찮고 불편한 상황!
☆ 해결방법: 우리멤버는 막 접근해도 된다는 장점이 있기때문에 우리멤버인 메소드 output을 정의해 출력한다.
메소드 output을 이용해 우리멤버를 한번에 출력할 수 있다. ScoreTest의 마지막 코드 System.out.println(s.getKor());처럼 getter를 이용해 하나씩 출력할 필요가 없어 편하다. output도 우리멤버이기 때문에 this를 붙이지 않아도 된다. (위에서는 확실하게 보여주기 위해 name에만 우리멤버임을 알리는 this를 사용했다.
메인메소드에서 sysout을 사용하지 않고, s.output();이라고만!
왜냐하면 output 메소드에 들어갈 변수들이 이미 main메소드에 대입되어있는 상태이기 때문이다.
▶setter를 통해 값이 대입되기 전과 후 output의 비교
값을 대입하지 않았을 경우, null, 0, 0.0 등 기본값으로 출력된 것을 확인할 수 있다.
▶대입받은 값을 가지고 구할 수 있는 평균을 구해주는 calcAvg라는 메소드를 calcAvg라는 만들어 보자.
평균 avg는 raw data가 아니라 이미 대입받은 국영수의 값으로 구하는 것이기때문에 대입받는 값을 의미하는 지역변수가 필요없다!
<6주차 질문1번 참고>
성적 수정으로 인해 수학점수를 재대입했다고 하자. 과연 성적변화로인해 평균에 변화도 있을까?
과학의 점수를 업데이트(수정)해도 평균 점수에 변화가 없음을 알 것!
그렇다면 국영수의 점수가 수정될 때마다 수정된 성적으로 평균을 낼 수 있는 방법은 없을까?
점수의 수정, 변화가 있다는 뜻은 지역변수를 우리멤버에 대입하는 setter의 값에 변화가 있다는 것!
setter에 외부의 값이 넣어질 때마다 평균을 계산하는 calcAvg();를 돌리는 것!
주의: 외부의 값을 우리멤버에게 집어넣을 때(대입 때)마다 사용됨으로 setter에만 사용가능. getter에는 넣고 싶어도 못넣음.
setKor/setEng/setMat가 호출, 변화될 때마다 평균값을 구하도록 하는 것이다. 그렇지 않으면 성적의 값에 변화가 있어도 업데이트되지 않는다. 실제로 이렇게 계산한다는 것은 아니고 같은 클래스의 메소드는 마음대로 쓸 수 있다는 것을 보여주는 예.
이렇게 메소드 calcAvg를 정의하고 호출하여 사용함에 따라 각각의 성적이 수정되어도 평균점수가 그에 맞게 변경됨을 알 수 있다.
printf로 소수점 정리한 출력값
[생성자 메소드(Constructor)]
-기본생성자 Score s =new Score();
- 객체를 메모리에 생성하고, 초기화하는 역할! 초기화만 하면 자신의 몫이 끝나기 때문에 ();
- 중요하기 때문에 사용자가 만들지 않으면 JVM이 자동으로 만들어준다. (기본생성자)
- 생성자 만들기 규칙
: 특별한 경우가 아니면 접근지정자 public으로 만들고 생성자의 이름은 클래스명과 동일하다.
public 클래스명( ) {
}
주로 나열되는 순서 : public -> private -> 생성자 -> setter/getter/ 정해진 것은 아니지만 주로 이렇게 사용
지금쯤이면 output 메소드의 쓰임을 알겠지?
메소드 output을 생성하지 않으면 f.getUserid();, f.getName(); ...이런 식으로 f.setName("임재범") 이렇게 대입한 값을 하나하나 불러와 확인해야 하기 때문에 값을 한번에 출력하는 output 메소드를 만들어 준 것이다. Okay?
getter를 사용해 일일이 출력할 필요없이 메소드 output에 우리멤버를 마음대로 사용해 sysout -> 이후 메소드 호출로 사용하면 간편!
▶setter/getter을 간단하게 만드는 방법
public class FitnessVO {
private String userid;
private String name;
private double height;
private double weight;
private double bmi;
private String result;
멤버변수를 다 적은 후, source → Generate Getter and Setter
setter와 getter가 필요한 멤버변수를 체크해주고 밑에 있는 Generate 버튼을 눌러주면 끝!
%fcm double형에 cm이라는 단위를 붙이는 방법
%fkg double형에 kg이라는 단위를 붙이는 방법
%.2f double형에 소수점 두자리까지만 출력하라는 표시
[키와 몸무게를 이용해 bmi 구하기]
Bmi 구하는 공식 = 몸무게 ÷ 신장의 제곱(단위 m)
키와 몸무게는 외부에서 값을 가져오지만 bmi는 가져온 키와 몸무게로 구할 수 있다. 즉 우리멤버 안에서 해결할 수 있다.
외부에서 값을 가져올 필요가 없기 때문에 public void calcBmi()의 괄호 ( ) 안은 비워둔다.
★(bmi를 계산할 때, setter에서 하느냐, getter에서 하느냐를 묻는다면) setter라는 이름을 가지고 있다하더라도 set에서 연산해야함.
(복습중.. 이제와 생각해보니 setter에 넣을 걸 고민해 볼 필요도 없었네) 왜냐하면 값을 수정 및 대입하는 것은 setter이기 때문에!
bmi는 키와 몸무게로 구할 수 있기때문에 키와 몸무게의 값을 집어넣는 역할인 메소드 setWeight와 serHeight의 값이 수정될 때마다 메소드 calcBmi();를 호출해 bmi의 값이 업데이트할 수 있게 한다.
에러남 다시 해보기
오류난 이유 : public void calcaBmi(double weight)에서 double weight를 뺴야함.
원래라면 setBmi 메소드였을 calcBmi의 괄호 안 지역변수(double bmi)가 사라진 이유는 bmi는 키와 몸무게로부터 연산 후 얻는 값이기 떄문에 외부에서 받아올 필요가 없어 비워두는 것이다.
키와 몸무게의 값이 수정될 때마다 bmi를 구하는 메소드를 호출해 수정된 값으로 bmi를 구할 수 있게 한다.
▷bmi를 가지고 고도비만, 중도비만, 정상 등 result를 구해보자
정상, 비정상 등의 결과를 setResult 또한 지역변수를 통해 외부의 값을 가져올 것이 아니다. 그렇기 때문에 지역변수의 자리는 비워둘 것!
calcResult를 호출하는 시점도 중요함
calcBmi를 지난 시점이여야 한다.
(내가 자꾸 헷갈리는 부분)
메소드 output에 bmi이고 result가 있으니까 알아서 출력할 거라고 생각하는데 메소드 calcBmi도 메소드 calc도 메소드이기 때문에 calcBmi();, calcResult(); 이런 식으로 호출을 꼭 해야 값을 출력할 수 있다.
출력값
위의 출력값을 보면 소수점이 너무 많이 나와 지저분하니까 정리해주기! 어떻게?
%.2f 소수점 정리해주기
%.2f
%.2f에서 .2 라는 표시는 소수점 밑의 자리 2자리만 표시한다는 기호이다.
[오후수업]
클래스는 가로
[알라딘 서평쓰는 클래스를 만들어라]
setter랑 getter 하고 그냥 sysout해서 출력한다고 출력되지 않음.
public void output(){
System.out.println();
}
[게시판 만들기]
클래스는 가로의 값을 이용해 만듦.
★main 메소드를 못만들고 들어왔을 경우 : main + ctrl + space
♣복습: 20210501 토요일 복습
'개발자로 가는 길(국비지원과정) > 1. Java' 카테고리의 다른 글
[질문] 6주차 (0) | 2021.04.27 |
---|---|
[210427화] 메소드 오버로딩, 생성자오버로딩, static, final 키워드 사용법, FitnessService의 CRUD (0) | 2021.04.26 |
[질문] 5주차_주말 복습 (0) | 2021.04.24 |
[210423금] 객체지향, Class 클래스, 향상된 for문 (0) | 2021.04.23 |
[210422목] 2차원 배열 + 거품정렬 알고리즘 (0) | 2021.04.22 |