(7) 클래스
0615 정리
클래스
클래스란 무엇인가?
간단히 유사한 객체들의 속성을 묶어놓은 집합체 라고 할 수 있다
클래스란 무엇인가?
객체지향 프로그래밍
OOP(Object Oriented Programming) 라고 한다
4가지의 특징이있는데
- 추상화
- 캡슐화
- 상속
- 다형성
하나 씩 살펴보도록 하자
추상화
추상화를 어떻게 하느냐에 따라 앞으로의 객체를 정의할 수 있다
"설계" 하는 부분이라고 생각하면 되겠다
캡슐화
- 객체를 이용할때 구성을 몰라도 용법만 알고있다면 사용가능하다
- "캡슐 감기약"을 생각하면된다
- 안에 뭐가있는지 모른다 하지만, 감기에 걸렸을때 먹는다
- "정보은닉" 을 하고있지만 용법을 알고있어서 사용가능
- 기존에 완성된 코드 + 내가만든 코드
- 이미 만들어진 콧물x , 열x , 기침x 코드가 있다
- 해당코드들에는 문제가 없다는 것을 확인했다!
- 해당코드들에는 문제가 없다는 것을 확인했다!
- ( 콧물x / 열x ) = 해당 캡슐은 문제 없음!
- ( 콧물x / 기침x ) = 해당 캡슐은 문제 있다!
ㅡ> 어느 구간에서 합쳐지면 문제가 생긴지 알 수 있음 - 개발시간 단축, 에러에 할애하는시간 단축
- 이미 만들어진 콧물x , 열x , 기침x 코드가 있다
상속
- + - * / 을 사용할수 있는 계산기를 개발 하였다
- + - * / 로그,sin,cos,지수 를 사용할 수있는
공학용 계산기를 개발할 예정이다
- + - * / 구현이 가능한 계산기를 개발했는데
또다시 + - * / 구현할 코드를 새로 작성할 것인가?
( + - * / ) +@ 로 개발하면 되지않을까?
- + - * / 구현이 가능한 계산기를 개발했는데
- 기존의 코드를 "부모", 하위의 객체들을 생성해낼때
"상속" 받아서 만든다고 표현한다 - "부모"코드는 하위코드들의 기본틀이 된다
다형성
같은 메소드를 실행하더라도, 다른결과를 볼 수 있다
클래스.메소드() 로 표현한다
ex) 강아지 . 소리내기( ) ㅡ> 멍멍
고양이 . 소리내기( ) ㅡ> 야옹
클래스가 어느부분인지 예를 들자면
학생들 짱구, 철수, 훈이, 유리, 맹구 등등 많은 학생들이 있다
"학생" 라는 의미가 "클래스"
"짱구, 철수, 훈이 유리, 맹구" 라는 의미가 "객체" 라고 생각하면 될거같다
비슷한 예시로
붕어빵 틀 - 클래스 / 붕어빵 - 객체 라고 생각하면 되겠다
ㅡ> 붕어빵 틀이 1개라고 붕어빵 1개만 만드는 것이 아니라 계속 찍어낼 수 있다
클래스를 만들어보자!
클래스를 만드는 코드는
1 2 3 | class 클래스이름{ } | cs |
여기서 중요한점
- 클래스의 첫 글자는 "대문자" 로 작성한다!
- 클래스의 이름은 어떤 목적으로 만들어졌는지 유추 가능하도록 작성한다!
" 붕어빵 틀 "을 만든 것이다
1 2 3 4 5 6 7 8 | class Circle{ //클래스는 대문자로 시작 ** int radius; // 멤버변수 - 클래스 내부에서 만들어진 변수 String name; void print() {// 멤버 함수 - 클래스 내부에서 만들어진 메소드 System.out.println(this.name+": "+this.radius); } } | cs |
해당 클래스를 메인에서 호출하여 사용해보자!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public static void main(String[] args) { Circle c1 = new Circle(); Circle c2 = new Circle(); Circle c3 = new Circle(); c1.radius= 10; c1.name= "도넛"; c2.radius= 50; c2.name= "피자"; c1.print(); c2.print(); c3.print(); } | cs |
클래스 객체명 = new 클래스( );
Circle c = new Circle( );
ex) 스캐너, 랜덤을 생각해보면 된다
Circle클래스의 c 의 객체를 생성했다
ㅡ> " 객 체 화 " ==" 인스턴스화 " 했다 라고 한다
new 가 객체화를 담당한다
클래스안에 정의한 것들을 사용하고 싶다면
해당 객체의 이름을 사용하면된다
c1 c2 c3 는 같은 클래스에서 객체화 됐다
하지만 서로를 공유하지는 않는다
ㅡ> 다들 "학생" 이지만 "짱구" "철수" "훈이" 인 것이다
c1 에는 10 반지름의 "도넛"
c2에는 50 반지름의 "피자"
c3 ** 에는 아무것도 초기화하지 않았다
클래스안에 정의한 메소드 print ( ) 를 통해 출력해보자
c1과 c2는 초기화한대로 나왔지만
c3는 초기화하지않았는데 "null" 값과 "0"값이 초기화 되어있다
클래스에서 만든 멤버변수는 기본적으로 초기화를 해준다!!
중요한 변수가있어서 꼭 초기화를 해야한다면 어떻해야하나
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 | package class02; class Student{ String name; int num; int score; Student(String name,int num,int score){ this.name=name; this.num=num; this.score=score; } void showInfo() { System.out.println(this.name+"학생은 "+this.num+"번: "+this.score+"점"); } } public class Test06 { public static void main(String[] args) { Student stu1=new Student("임꺽정",100,80); Student stu2=new Student("홍길동",101,95); stu1.showInfo(); stu2.showInfo(); } } | cs |
학생의 정보를 저장할 Student 라는 클래스를 만들었다저장할 멤버변수로 이름, 번호, 점수 이다
이 프로그램을 사용하려고 하는데만약 이름을 안넣는다, 점수를 안넣는다 실수할 수 있다
까먹을 수 있기때문에 이럴땐 생성자를 이용하여 강제 할 수 있다
초기화해야하는 변수를 강제로 input 값을 넣게 만들어 놓을 수 있다
void Student ( String name, int num, int score) 메소드의 형태를 띄고있는데
이를 "생성자" 라고한다
생성자는 함수의 한 종류라고 할 수 있다
메서드 시그니처중 output이 없다
ㅡ> 생성자는 어차피 객체를 만들것이란걸 알기때문에 없는 것이다
해당 생성자는 input으로 입력받을 변수명 " name " 이 있고
안쪽에는 " this.name "이 있다
this.name = name; 으로 대입하는데
this를 붙인 변수는 해당클래스에서 선언한 name을 뜻하고
name은 해당메소드에서 선언한 name을 뜻한다
같은 이름을 사용하는 이유는
입력받은 name이 그대로 this.name에 저장되기때문에"가독성" 이 뛰어나다
마찬가지로 showInFo( )를 이용하여 저장된 값을 보여주도록 하였고결과를 보면
중요한 변수를 input값으로 보내주는데..
그냥 안넣고도 가능했는데 왜 오류가 날까..?
클래스 안에는 "기본 생성자"를 제공해주는데 안보일 뿐이다
ㅡ> 인자가 없는 생성자 == 기본(디폴트) 생성자를 기본으로 제공해준다
생성자도 결국엔 함수라고 생각하면된다
input값의 종류, 갯수, 순서로 동일한 이름의 함수로써 생성자를 만들수있다
이를 전에도 공부했었는데 클래스의 "오버로딩" 이라고 한다
기본생성자를 제공해주지만 (안보임)생성자를 1개이상 만들었다면
제공해준 기본생성자가 사라진다
그래서 다시 기본생성자를 사용하고 싶다면 만들어 주어야한다
예시 1)
예시 2)
주로 클래스를 만들때
멤버변수값을 맨 위로
기본생성자를 생성자중에 가장위에 표현하는게 좋을 것 같다
" 가독성 " 을 위해서
0616 ~ 0617 정리
이어서 진행합니다...
클래스 내에서 정의하는 변수와 메소드는
"멤버 변수" - " 속성, 필드, 어트리뷰트, 애트리뷰트 "
"멤버 함수" - " 멤버 메소드 "
개발자의 환경
에 따라
불리는 이름
이 다를 수 있다
- 실무에선 바탕화면에 따로 메모를 띄워서 이해할 수 있도록 적어두면 좋다
클래스 에서도 메소드를 만들 수 있는데, 이를 "멤버 함수" 라고 부르고
void 메소드명 ( ) { }으로 작성한다
- 기본형이며, static이 없는 이유는 객체에서 쓸걸 알기때문이다
- static = "객체와 무관하게 "
함수 이기때문에 아래의 순서를 생각하며 메소드를 만들자
- 메소드의 기본형을 갖춘다
- 기능을 구현한다
- input과 output이 올바른지 체크한다
생성자 심화과정
1 2 3 4 5 6 7 8 9 10 11 | Car(String name){ this.name=name; this.speed=0; this.maxSpeed=120; } Car(String name, int speed, int maxSpeed){ this.name=name; this.speed=speed; this.maxSpeed=maxSpeed; } | cs |
생성자 2개가 있다해당생성자의 차이는 input의 차이로 인해 "오버로딩"된 생성자이다
생성자 안에 입력값을 멤버변수에 대입하고있는데
생성자 두개 같은 코드를 사용하고있다
그래서 이런식으로 표현이 가능하다
1 2 3 4 5 6 7 8 9 10 11 12 | Car(String name){ this(name,0,120); // this.name=name; // this.speed=0; // this.maxSpeed=120; } Car(String name, int speed, int maxSpeed){ this.name=name; this.speed=speed; this.maxSpeed=maxSpeed; } | cs |
this( ) 를 이용하여 사용가능한데
- this .
- this == 자기자신 즉, 객체를 뜻한다
- this == 자기자신 즉, 객체를 뜻한다
- this ( ) (함수)
- 자기자신 ( ) 즉, 자신과 같은 생성자를 표현한 것
같은 이름의 "오버로딩" 되어있는 자신의 생성자
- 자기자신 ( ) 즉, 자신과 같은 생성자를 표현한 것
자신의 생성자 안에서 this( )를 사용하게 되면
자신을 표현하는 생성자를 사용하겠다! 라는 뜻이 되겠다
그래서 입력받은 input값 외에 값을 따로 입력해주어
"오버로딩"한 자신의 생성자를 생성자 안에서 사용한 것이다
- this ( ) 를 이용할 때는
- 인자가 가장많은 생성자만 놔둔다
- 다른생성자에서 위의 생성자를 불러 사용한다
결과적으로 불필요한 반복코드를 줄일 수 있다!
값을 공유하는 멤버변수!
객체는 자기 자신만의 값을 가지고있어 객체끼리에는 영향을 끼치지 않는다
하지만 은행카드를 생각해보자
통장은 하나 이지만 그에 관련된 여러개의 카드를 만들 수 있다. 이를 통해
통장 = 클래스
여러개의 카드 = 객체
로 표현할 수 있겠는데, 한통장에서 나온 카드 들 이기에
통장의 "잔액"은 카드들이 "공유하는 변수"라고 할 수 있다
이러한 변수를 " 클래스 변수 " 라고 부른다
표현하는 방법은 앞에 static을 붙여서 사용한다
1 2 3 4 5 | class Card { String name; // 사용자이름 int limit; // 한도 static int bal=200000; // 잔액 : 공유할 변수 } | cs |
static = " 객체와 무관하게 "
Card의 객체들은 각자의 이름과 한도가 정해져 있지만
bal (잔액)은 공유하는 "클래스 변수"로 표현해 보았다
그래서 각자의 객체를 이용할때 bal라는 클래스변수를 이용하게되면
모든 객체의 bal의 값이 이용한 값으로 변형된다
객체를 배열에 저장해보자!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package class01; class Sand { String name; static int sand = 100; Sand (String name) { this.name=name; } } public class Test01 { public static void main(String[] args) { Sand p1 = new Sand("홍길동"); Sand p2 = new Sand("아리"); Sand p3 = new Sand("티모"); }// main }// class | cs |
위 코드는 p1 p2 p3 객체로 생성했다!
클래스의 생성자를 확인하면 이름만 필요한 생성자임을 확인 할 수 있다
같은이름(String)만 input값으로 넣는 같은종류의 코드들이다
객체생성 코드를 보면 모두 new를 이용하여 객체를 생성하고있다
이를 좀더 편하게 "배열"로서 객체를 생성해보자
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 | package class01; class Sand { String name; static int sand = 100; Sand (String name) { this.name=name; } } public class Test01 { public static void main(String[] args) { Sand[] p = new Sand[3]; p[0] = new Sand("홍길동"); p[1] = new Sand("아리"); p[2] = new Sand("티모"); // Sand p1 = new Sand("홍길동"); // Sand p2 = new Sand("아리"); // Sand p3 = new Sand("티모"); }// main } | cs |
기본식
클래스[ ] 식별자 = new 클래스[ int ];
Sand[ ] p = new Sand [ 3 ] ;
- Sand [ ] P
- Sand 배열의 p식별자를 가진
- Sand 배열의 p식별자를 가진
- = new Sand [ 3 ];
- 3개의요소를 가진 Sand 배열의 객체를 생성하겠다!
Sand [ index ] 이고, 각자 하나의 객체라고 생각하면된다!
이 인덱스를 이용할 게임을 하나 만들었다
"모래성 가져가기 게임"
모래성은 100으로 시작하여
차례로 1~20의 모래를 가져가
모래성이 0이하가 되면 게임오버
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 | // 클래스 Sand 안에 있는 메소드 boolean play( ) { Random r = new Random(); int num = r.nextInt(20) +1; System.out.print(this.name+"님이 모래성에서 모래를 "+num+"만큼 파냈습니다"); this.sand -= num; System.out.println("현재모래성 : "+this.sand); if(this.sand <= 0) { System.out.println("게임오버"); return true; } return false; } // --------------------- 메인메소드 ------------------------ while(true){ int i = 0; // index번호를 나타내줄 변수 if(p[i].play()) {// 종료조건 (게임오버가 된다면) break; } i++; // 다음사람차례 == 배열차례 if(i==p.length) {//마지막배열순서가 지나면 i++되어 // length와 숫자가 같아진다! i=0; // 다시 0번부터 } } | cs |
play( ) 를 실행하면
- 한 객체(사람)이 모래를 1~20을 판다
- 만약 모래를 판뒤에 0이하라면 게임오버의 조건이 있다
- flag 변수로 게임오버가 되면 신호를 보낸다
while을 사용한 이유는 게임 오버까지 몇번반복할지 알수 없음
배열은 for문과 어울리기때문에 for문으로 표현하면 되지만
while 안에서 표현이 가능하기때문에 int = i 를 생성하여 코드를 만들었다
종료조건으로는 게임종료의 return값 true를 받게되면
break; 할 수 있도록 조건을 만들었다
- 그래서 play( )의 output을 boolean으로 이용하여 신호를 받았다
이렇게 배열을 이용한 객체생성이 가능하다!
그리고 해당 배열객체를 이용하여 활용할 수 있다!