6. 클래스
6.1 객체지향프로그래밍
제품 부품만들고 조립함.
소프트웨어 웹 애플리케이션 개발 시 세부 객체들을 설계하고 만들고 조립하고 만드는것
이것이 객체 지향프로그래밍 엔진등 하나씩 만들어서 조립
객체란?
데이터와 메소드로 구성된 덩어리
물리적으로 존재하거나 개념적인 것 중에서 다른것과 식별가능한 것
객체 속성(데이터)과 동작(메소드)
자바 소프트웨어로 객체 모델링 / 속성을 필드로 동작을 메소드로
현실세계의 객체를 소프트웨어 객체로 설계하는것을 객체 모델링이라고 한다.
현실속엔 객체가 너무 많아서 대표 속성과 동작을 추려내어 소프트웨어 객체의 필드와 메소드로 정의하는 것이다.
객체지향프로그램밍의 특징
부품을 만들고 부품들을 조립해서 부품들로 완성품을 만드는 것
1.캡슐화
보호한다. 객체를 만들면 안에 데이터 메소드 잇음. 데이터와 메소드 모든 다른 객체에서 이용할 수 있는 것은아님.
일부는 사용가능 일부는 전자계산기 안에서만 사용가능
객체를 설계할때 어떤부분은 쓰도록 보여주고 어떤부분은 내부에서만 사용하도록 설계
접근제한자를 사용하여 만든다.
2.상속
부모라는 객체 사이 객체와 자식역할의 하위객체가 있다.
부모객체는 자기가 가지고 있는 필드와 메소드를 자식객체에게 무려주어 자식객체가 사용할수있도록한다.
코드의 재사용성을 높여줌. 잘 개발된 부모 객체의 필드와 메소드를 자식이 그대로 사용할 수 있어 자식 객체에서 중복코딩 안함.
유지보수 시간을 최소화 부모 객체필드에서 수정되면 모든 자식 객체들은 수정된 필드와 메소드들 사용함.
자식을 여러개 만들수 있음. 자식또한 자식만 가진 필드를 가질수 잇음.
3.다형성
사용방법은 동일한데 실행결과가 다양하게 나오는 성질
자동차에서 부품을 바꾼다 ex)타이어 사용방법은 동일함. 그러나 타이어 장착에따라 성능이 다름.
'자동타입변환'과 '재정의' 기술이 필요하다. 이는 상속 인터페이스 구현을 통해 얻어진다.
6.2 객체와 클래스
클래스 : 객체를 생성하기 위한 설계도, 청사진
클래스를 가지고 -> 객체를 만드는것 '인스턴스화' 한다
만들어진객체를 인스턴스라고도 한다.
하나의 설계도로 여러객체를 만들 수 있음. 설계도하나에 여러 객체
설계도 클래스를 만드는게 중요하다.
6.3 클래스선언
필드 생성자 메소드
6.4 객체생성과 클래스 변수
객체는 메모리에 생성됨. 메모리에 생성되는걸 사용해야하는데 어디 메모리에 객체가 있느냐를 알아야함.
번지를 가지는 것임. 번지? 참조타입 힙영역에 객체가 생김
메모리번지를 변수에 저장해야 함. 변수로 객체를 사용할 수 잇다.
클래스 변수 = new 클래스이름(); 변수에는 클래스로 만든 객체의 번지가 저장되어잇음 이 변수는 참조파일이됨.
new는 객체를 만드는 연산자임. 어떤 이름에서 클래스를 만들것이냐?
main에서 부품을 조립하는 것이고 객체생성은 설계도를 가져와서 부품을 만들어 놓는 것임.
클래스의 두가지용도
1.라이브러리(library) 클래스: 실행할수 없으며 다른 클래스에서 이용하는 클래스
2.실행클래스 : main()메소드를 가지고 있는 실행가능한 클래스
실행클래스는 실행하면서 라이브러리 클래스를 내부에서 이용한다.
6.5 클래스의 구성멤버
1.필드 : 데이터를 저장하는 역할
2.생성자 : 생성하는 자 객체를 생성하는 것 객체의 초기화 역할을 담당
3.메소드 : 객체가 수행할 동작 다른 프로그램언어에서는 함수 라고도 함. 객체 내부의 함수는 메소드라고 부른다. 메소드는 객체와 객체간의 상호작용을 위해 호출된다.
6.6 필드의 선언과 사용
필드는 객체의 데이터를 저장하는 역할 객체의 데이터에는 고유데이터 /현재 상태 데이터 수시로 변경 예) 차속도/부품데이터 자동차를 만드는 부품이 있다.
6.6.1 필드선언
데이터들 필드 선언은 변수선언과 동일하지만 필드라고 한다.
필드타입 필드명 [=초기값];
반드시 클래스블록에서 선언되어야만 필드이다.
필드와 변수의 차이점
선언위치 필드 클래스 선언블록 / 변수 생성자 메소드선언블록 -> 클래스선언블록에서 선언한거 제외하고는 전부다 변수임.
존재위치 필드 객체 내부에 존재 / 변수 생성자 메소드 호출시에만 존재(잠깐만들어지고 없어지는 존재임.)
사용위치 필드 객체 내외부 어디든사용 / 변수 생성자 메소드 블록내부에서만 사용.
타입은 필드에 저장할 데이터의 종류를 결정 기본타입(byte short int long float double boolean)와 참조타입(배열 클래스 인터페이스) 모두 가능
String model = "그랜져"; // 고유데이터 필드
int speed = 300; // 상태데이터필드
boolean strat = true;
Tire tire = new Tire(); // 부품객체 필드 Tire클래스 필요설계도에 초기값이 들어가잇으면 이걸로 객체를 만들면 초기값이 들어가잇음.
초기값 제공하지 않으면 자동으로 기본값으로 초기화된다.
6.6.2 필드사용
필드를 사용한다는 것은 필드값을 읽고 변경하는 것을 말한다.
클래스에서 필드를 선언한다고 바로 사용할 수 있는 것은 아님.
필드는 객체데이터이므로 객체가 존재하지 않으면 필드도 존재하지 않는다.
1.생성자 블록안에서 필드의 값을 읽거나 변경하기
2.메소드 블록안에서 하기.
3.외부객체에서 생성 변경하기 객체 외부에서는 변수.객체(도트연산자)로 가기
Car myCar = new Car();
myCar.필드명 6.7 생성자 선언과 호출
객체를 생성할때 생성자를 호출해서 객체를 초기화하는 역할을 한다.
객체 초기화란 필드초기화를 하거나 메소드를 호출해서 객체를 사용할 준비를 하는 것을 말한다.
클래스 변수 = new 클래스명();
보통 생성자가 클래스명() {} 로 생겼는데
new연산자를 통해 new 클래스명()생성자를 부르고 생성자의 {실행문}을 실행시키는 것이다.
그래서 클래스 변수 = new 클래스명();에서 우측을 생성자 호출이라고 부르는 것이다.
생성자호출을 해서 객체를 초기화하는 것이다.
객체초기화란 필드 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 하는것임. 사용자가 사용하기 직전까지 준비
생성자를 호출해야 객체를 사용할 수 있게 됨.
6.7.1 기본생성자
생성자를 만들지 않으면 [public] 클래스() {}이 컴파일 단계에서 자동으로 생긴다.
그래서 new연산자뒤에 기본생성자를 호출 할 수 있다.
개발자가 명시적으로 생성자를 선언하는 경우가 더 많다.
6.7.2 생성자 선언
객체를 다양하게 초기화하기 위해 개발자가 생성자를 직접선언한다.
생성자는 메소드와 비슷한 모양을 가지고 있으나 리턴 타입이 없고 클래스 이름과 동일하다.
매개변수는 new연산자로 생성자를 호출할때 매개값을 생성자 블록내부로 전달하는 역할을한다.
Car mycar = new Car("그랜저", "검정", 300); car생성자를 호출할때 3개의 매개값을 호출할때 3개의 매개값을 블록내부로 전달한다고 가정해보자.
3개의 매개값을 순서대로 매개변수로 대입받기 위해서는 생성자가 선언되어 있어야한다.
Car(String model(매개변수), String color(매개변수), int maxSpeed){...}
매개변수의 타입은 매개값의 종류와 맞게 작성하면된다.
각각 매개변수에 저장이되어서 사용할 수 있다. 매개변수의 수만큼 안넣으면 컴파일에러발생
6.7.3 필드초기화
객체마다 동일한 값을 가지고 있다면 필드 선언시 초기값을 대입하는 것이 좋고 객체마다 다른값을 가져야한다면 생성자에서 필드를 초기화하는 것이 좋다.
필드값 넣는 행위는 클래스선언시, 객체를 만들때 할 수 있다.
예를들어 Korean클래스를 선언한다고 가정해볼때 한국인이므로 nation(국가)는 대한민국으로 동일한 값을 가지지만 name(이름)과 ssn(주민번호)는 한국인마다 다르므로 생성자에서 초기화하는 것이 좋다.
Korean k1 = new Korean("박자바", "011225-1234567");
Korean k2 = new Korean("김자바", "930525-0654321");
package ch06ver2.sec07;
public class Korean {
//필드선언
String nation = "대한민국";
String name;
String ssn;
public Korean(String name, String ssn) {
this.name = name;
this.ssn = ssn;
}}package ch06ver2.sec07;
public class KoreanExample{
public static void main(String[] args) {
//korean객체생성
Korean k1 = new Korean("박자바", "011225-1234567");
System.out.println("k1.nation : " + k1.nation);
System.out.println("k1.name : " + k1.name);
System.out.println("k1.ssn : " + k1.ssn);
Korean k2 = new Korean("김자바", "930525-0654321");
System.out.println("k2.nation : " + k2.nation);
System.out.println("k2.name : " + k2.name);
System.out.println("k2.ssn : " + k2.ssn);
}}생성자가 어떻게 활용되는 지를 모르는 경우가 잇다.(내가 설계안햇을 경우)
그래서 매개변수를 필드의 이름과 같게 만들어주는게 좋다.
매개변수를 받은것을 필드에 곧바로 넣는 경우가 생긴다.
생성자 안에서는 this.필드명 = 매개변수를 해서 구분되도록하기.
객체 내부의 이름 this. 내가 가지고 있는 것의미하게
6.7.4 생성자 오버 로딩
매개값으로 객체의 필드를 다양하게 초기화하려면 생성자 오버로딩이 필요하다.
생성자 오버로딩이란 매개변수를 달리하는 생성자를 여러개 선언하는 것을 말한다.
매개변수의 타입이 다르거나 갯수를 다르게 선언하는 것임.
생성자 오버로딩 왜하나?
매개값으로 객체의 필드를 다양하게 초기화기 위해서
생성자는 어떤것으로도 객체를 생성할수 잇기때문에 어떤걸로도 만들수 있는데 어떤것을 사용할지는 개발자의 선택이다.
융통성을 주기위해 여러개를 만드는 것임.
6.7.5 다른 생성자 호출
생성자 오버로딩이 많아질경우 생성자간의 중복된 코드가 발생할 수 있다.
매개변수의 수만 달리하고 필드 초기화 내용이 비슷한 생성자에서 중복코드를 많이 볼 수있다.
이경우에는 공통코드를 한 생성자에만 집중적으로 작성하고 나머지 생성자는 this(...)를 사용하여 공통 코드를 가지고 있는 생성자를 호출하는 방법으로 개선할수잇다.
마지막에만 공통초기화 코드를 넣기.
this(매개값..)으느 생성자의 첫줄에 작성되며 다른 생성자를 호출하는 역할을한다. 호출하고 싶은 생성자의 매개변수에 맞게 매개값을 제공하면된다.
this()다음에는 추가적인 실행문을 작성할수 있는데 호출되는 생성자 실행이 끝나면 원래 생성자로 돌아와서 다음 실행문을 실행한다.
Car(String model){
this(model,"은색",250);
//다른실행문
}
Car(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
}위의경우 첫번째 생성자를 쓰면 두번째 생성자를 불러온후 돌아와서 다른 실행문을 또 실행한다.
package ch06ver2.sec07;
public class Car {
String company = "현대자동차";
String model;
String color;
int maxSpeed;
//오버로딩
Car(){}
Car(String model){
this.model = model;}
Car(String model, String color){
this.model = model;
this.color = color;}
Car(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
}
//다른생성자 호출
Car(String model){
this(model,"은색",250);
System.out.println("1");
}
Car(String model, String color){
this(model,color,250);
System.out.println("2");
}
Car(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
System.out.println("3");
}}6.8 메소드 선언과 호출
메소드 선언은 객체의 동작을 실행블록으로 정의하는것
{}안쪽이 객체가 행동을 하는 것임.
6.8.1 메소드선언
int add(int x, int y) { <-메소드 선언부
int result = x + y; <- 실행블록
return result;}
선언과 호출로 이루어짐.
이 호출코드는 객체 내부에서나 객체 외부에서도 호출 할 수 있다.
리턴타입 메소드면(매개변수,...) {실행블록} 호출을하고나서 돌려받는값 = 리턴
리턴타입
리턴타입 void 리턴값이 없는 것
다른타입이오면 return문으로 리턴 값을 받드시 지정해야한다.
메소드명은 캐멀스타일
매개변수 메소드를 호출할때 전달한 매개값을 받기위해 사용한다. 전달할 매개값이 없다면 생략가능.
return은 메소드선언부 리턴타입과 같거나 자동타입변환이 될 수 있어야함.
//리턴값이 없는 메소드 선언
void powerOn()
{
System.out.println("전원을 켭니다.");
}
//리턴 값이 없는 메소드 선언
void powerOff()
{
System.out.println("전원을 끕니다.");
}
//호출시 두 정수 값을 전달받고
//호출한 곳으로 결과값 int를 리턴하는 메소드 선언
int plus(int x, int y)
{
int result = x + y;
return result; //리턴값 지정
}
//호출시 두 정수 값을 전달받고
// 호출한 곳으로 결과값 double를 리턴하는 메소드 선언
double divide(int x, int y)
{
double result = (double) x / (double) y;
return result;
}6.8.2 메소드호출
메소드 호출은 메소드 블록을 실행하는 것이다.
클래스로부터 객체가 생성된 후에는 메소드는 생성자와 다른 메소드 내부에서 호출 될 수 있고 객체 외부에서도 호출될 수 있다.
객체외부에서는 객체 참조변수 = new 생성자(); 한 후에 참조변수.메소드();필요
6.8.3 가변길이 매개변수
경우에따라서는 메소드에 매개변수가 몇개인지 모르는 경우가 있다.
좀처럼 그럴일이 없지만 그럴수도 있다.
int sum(int ... values){} 이건 배열이고 낱개로 제공하거나 배열자체를 줘도됨.
int타입에 몇개가 올지 모르겠어서 사이에 '...' 이들어가있다.
int result = sum(1,2,3); or int result = sum(1,2,3,4,5); // 같은 타입만 가능 그러나 갯수는 정해져잇지않음.
매개값들은 자동으로 배열항목으로 변환되어 메소드에서 사용된다. 그렇기 때문에 호출시 직접 배열을 매개값으로 제공해도된다.
int[] values = {1,2,3};
int result = sum(values);
int result = sum(new int[] {1,2,3});
package ch06ver2.sec08;
public class Computer {
//가변길이를 매개변수를 갖는 메소드 선언
int sum(int ... values)
{
//sum 변수 선언
int sum = 0;
//values는 배열 타입의 변수처럼 사용
for (int i =0; i < values.length; i++)
{
sum += values[i];
}
//합산결과를 리턴
return sum;
}}Computer myCom = new Computer();
//sum()메소드 호출 시 매개값 1,2,3을 제공하고 합산겨로가를 리턴받아 result1변수에 대입
int result1 = myCom.sum(1,2,3);
System.out.println("result1: " + result1);
//sum()메소드 호출시 배열을 제공하고 result2 변수에 대입
int[] values = {1,2,3,4,5};
int result2 = myCom.sum(values);
System.out.println("result2: " + result2);
//sum()메소드 호출시 배열을 제공하고 합산결과를 리턴받아 result3에 대입
int result3 = myCom.sum(new int[] {1,2,3,4,5});
System.out.println("result3: " + result3);6.8.4 return문
메소드의 실행종료, 리턴값을 지정할때 사용한다.
리턴문; 다음의 실행문은 실행안됨.
int plus(int x, int y ) {
int result = x+y;
return result;
System.out.println(result); //이부분은 리턴문 다음이기때문에 Unreachable code(죽은코드)가되어 컴파일에러가 발생한다.
}6.8.5 메소드 오버로딩
메소드 오버로딩은 메소드이름만 같되 매개변수의 타입 개수 순서가 다른 메소드를 여러개 선언하는 것을 말한다.
//정사각형 넓이 구하기
double areaRectangle(double width)
{
return width * width;
}
//직사각형 넓이 구하기
double areaRectangle(double width, double height)
{
return width * height;
}6.9 인스턴스 멤버
클래스를 가지고 객체를 만드는것이 인스턴스화이고 결국 인스턴스=객체이다.
인스턴스멤버는 결국 객체 멤버라고 할 수 있다.
필드와 메소드는 선언 방법에 따라 인스턴스 멤버와 정적멤버로 분류할 수 있다.
생성자는 왜 없냐? 생성자로 객체를 만들기 때문에 이미 객체가 만들어지면 생성자를 부를일이 없기때문임.
정적과 구분하기 위해서 인스턴스 멤버라고 부른다.
정적멤버는 클래스에 고정된 멤버라고 할 수 있다.
인스턴스멤버 선언 및 사용
인스턴스 멤버는 객체가 있어야만 사용할 수 있다.
Car객체를 먼저 생성하고 참조변수로 접근해서 사용해야 한다.
외부 클래스에서 사용하기 위해서는 car객체를 먼저 생성하고 참조변수로 접근해서 사용해야한다.
메소드는 코드의 덩어리 이므로 객체마다 저장한다면 중복 저장으로 인해 메모리 효율이 떨어진다.
따라서 메소드 코드는 메소드 영역에 두되 공유해서 사용하고 이때 객체 없이는 사용하지 못하도록 제한을 건것임.
'기초단계 > JAVA' 카테고리의 다른 글
| 2022.12.15 JAVA 복습 상속 (0) | 2022.12.15 |
|---|---|
| 2022.12.14-6 JAVA 복습 클래스 (0) | 2022.12.14 |
| 2022.12.14-4 JAVA 복습 참조타입 (0) | 2022.12.14 |
| 2022.12.14-3 JAVA 복습 조건문과 반복문 (0) | 2022.12.14 |
| 2022.12.14-2 JAVA 복습 연산자 (0) | 2022.12.14 |