객체지향 프로그래밍 - 로직을 상태(state)와 행위(behave)로 이루어진 객체로 만드는 것
상태>변수
행위>메소드
부품화 - 문제 해결이 쉬워짐
분리하는 기준을 세우는 것 - 추상화
핵심: 연관된 메소드와 그 메소드가 사용하는 변수들을 분류하고 그룹핑 하는 것!!
은닉화, 캡슐화 - 사용하는 방법만 알면 쓸 수 있어야 한다. 동작 방법은 숨긴다.
인터페이스 - 부품과 부품을 서로 교환할 수 있어야 한다. 연결점.
복제,상속
메소드화
System.out.println(10 + 20);
System.out.println(20 + 40);
-> 중복을 제거하는 것
public class CalculatorDemo2 {
public static void sum(int left, int right) {
System.out.println(left + right);
}
public static void main(String[] args) {
sum(10, 20);
sum(20, 40);
}
}
평균도 구하려면-?
public class ClaculatorDemo3 {
public static void avg(int left, int right) {
System.out.println((left + right) / 2);
}
public static void sum(int left, int right) {
System.out.println(left + right);
}
public static void main(String[] args) {
int left, right;
left = 10;
right = 20;
sum(left, right);
avg(left, right);
left = 20;
right = 40;
sum(left, right);
avg(left, right);
}
}//입력값을 변수화시켜서 메소드가 변수들을 사용하도록 한다
객체화
변수나 메소드의 이름이 겹치게 된다면-?
핵심 : 연관된 변수와 메소드를 하나의 그룹으로 묶는 것!!
그룹
left = 10;
right = 20;
sum(left, right);
avg(left, right);
class Calculator{
int left, right;
public void setOprands(int left, int right){
this.left = left;
this.right = right;
}
public void sum(){
System.out.println(this.left+this.right);
}
public void avg(){
System.out.println((this.left+this.right)/2);
}
}//Calculator 클래스 안의 변수 left, right, 메소드 setOperands, sum, avg
public class CalculatorDemo4 {
public static void main(String[] args) {
Calculator c1 = new Calculator();//Calculator타입의 인스턴스 c1 생성
c1.setOprands(10, 20);
c1.sum();
c1.avg();
Calculator c2 = new Calculator();
c2.setOprands(20, 40);
c2.sum();
c2.avg();
}
}
this : 인스턴스 자신을 가리킴
메소드 밖에서 선언한 left, right 변수 - 인스턴스 내의 모든 메소드에서 접근 가능
하나의 클래스를 바탕으로 서로 다른 상태(변수)를 갖는 인스턴스를 만들면 서로 다른 결과가 나오는 행동을 한다
클래스 멤버와 인스턴스 멤버
1)모든 인스턴스가 같은 값을 공유하게 하려면-?
변수를 클래스의 멤버로!
class Calculator {
static double PI = 3.14;//static을 붙이면 클래스 소속이 됨
int left, right;
public void setOprands(int left, int right) {
this.left = left;
this.right = right;
}
public void sum() {
System.out.println(this.left + this.right);
}
public void avg() {
System.out.println((this.left + this.right) / 2);
}
}
//클래스 변수에 접근하는 방법
public class CalculatorDemo1 {
public static void main(String[] args) {
Calculator c1 = new Calculator();
System.out.println(c1.PI);//인스턴스를 통해 접근
Calculator c2 = new Calculator();
System.out.println(c2.PI);
System.out.println(Calculator.PI);//클래스를 통해 접근 : 인스턴스를 생성할 필요가 없음
}
}
2)변수의 변경사항을 모든 인스턴스에서 공유하려면-?
class Calculator2 {
static double PI = 3.14;
// 클래스 변수인 base가 추가되었다.
static int base = 0;
int left, right;
public void setOprands(int left, int right) {
this.left = left;
this.right = right;
}
public void sum() {
// 더하기에 base의 값을 포함시킨다.
System.out.println(this.left + this.right + base);
}
public void avg() {
// 평균치에 base의 값을 포함시킨다.
System.out.println((this.left + this.right + base) / 2);
}
}
public class CalculatorDemo2 {
public static void main(String[] args) {
Calculator2 c1 = new Calculator2();
c1.setOprands(10, 20);
// 30 출력
c1.sum();
Calculator2 c2 = new Calculator2();
c2.setOprands(20, 40);
// 60 출력
c2.sum();
// 클래스 변수 base의 값을 10으로 지정했다.
Calculator2.base = 10;
// 40 출력
c1.sum();
// 70 출력
c2.sum();
//모든 인스턴스의 base값이 10으로 변경됨
}
}
클래스 변수의 용도
1. 인스턴스에 따라서 변하지 않는 값이 필요한 경우 (위의 예에서는 PI)
(이런 경우 final을 이용해서 상수로 선언하는 것이 바람직 하지만 final을 아직 배우지 않았기 때문에 언급하지 않았다)
2. 인스턴스를 생성할 필요가 없는 값을 클래스에 저장하고 싶은 경우
3. 값의 변경 사항을 모든 인스턴스가 공유해야 하는 경우
클래스 메소드
class Calculator3{
public static void sum(int left, int right){
System.out.println(left+right);
}
public static void avg(int left, int right){
System.out.println((left+right)/2);
}
}
public class CalculatorDemo3 {
public static void main(String[] args) {
Calculator3.sum(10, 20);
Calculator3.avg(10, 20);
Calculator3.sum(20, 40);
Calculator3.avg(20, 40);
}
}//인스턴스를 생성하지 않고 (인스턴스 변수 참조 X) 클래스 메소드만 사용-> 불필요한 인스턴스를 생성하지 않는다
원칙
1. 인스턴스 메소드는 클래스 멤버에 접근 할 수 있다.
2. 클래스 메소드는 인스턴스 멤버에 접근 할 수 없다.
클래스가 생성된 후에 인스턴스가 생성되기 때문!!
클래스->클래스 메소드, 클래스 멤버 접근 가능
인스턴스->클래스 메소드, 클래스 멤버, 인스턴스 메소드, 인스턴스 멤버 접근 가능
유효범위
public class ScopeDemo2 {
static int i;
static void a() {
i = 0;//static int i 클래스에서 선언된 변수, 전역변수
}
public static void main(String[] args) {
for (i = 0; i < 5; i++) {
a();
System.out.println(i);
}
}
}
//클래스 변수 i를 사용, a()로 계속해서 0으로 초기화 -> 무한 반복!!
public class ScopeDemo3 {
static int i;
static void a() {
int i = 0;//메소드 안에서 선언한 변수는 메소드가 실행될 때 만들어지고, 종료되면 삭제된다. 지역변수
}
public static void main(String[] args) {
for (i = 0; i < 5; i++) {
a();
System.out.println(i);
}
}
}
메소드 내에 지역변수가 존재하지 않으면 메소드가 소속한 클래스의 전역변수를 사용한다. (클래스 변수)
class C3 {
int v = 10;
void m() {
int v = 20;
System.out.println(this.v);
}
}
public class ScopeDemo9 {
public static void main(String[] args) {
C3 c1 = new C3();
c1.m();
}
}
class C3 {
int v = 10;
void m() {
int v = 20;//지역변수 v=20
System.out.println(this.v);//인스턴스의 v=10
}
}
public class ScopeDemo9 {
public static void main(String[] args) {
C3 c1 = new C3();
c1.m();
}
}
초기화 - 생성자
Calculator c1 = new Calculator();
c1.setOprands(10, 20);//left,right를 설정하기 위해 메소드 호출해야 함
c1.sum();
c1.avg();
생성자- 객체를 생성할 때 호출
public Calculator(int left, int right) {
this.left = left;
this.right = right;
}//left,right를 설정하는 과정을 객체 생성 과정에서 강제할 수 있게 됨!
생성자 특징 : 값을 반환하지 않음, 클래스 이름과 동일한 이름
상속
객체지향의 목표인 재활용성을 극대화
객체의 변수와 메소드를 다른 객체에게 물려주는 기능
기존의 객체를 수정하지 않으면서 새로운 객체가 기존의 객체를 기반으로 만들어지게 되는 것.
부모 클래스와 자식 클래스의 관계를 상위(super) 클래스와 하위(sub) 클래스라고 표현하기도 한다. 또한 기초 클래스(base class), 유도 클래스(derived class)라고도 부른다.
class SubstractionableCalculator extends Calculator {
public void substract() {
System.out.println(this.left - this.right);
}
}
SubstractionableCalculator c1 = new SubstractionableCalculator();
c1.setOprands(10, 20);
c1.sum();
c1.avg();
c1.substract();
//Calculator에 정의된 메소드를 사용할 수 있음
상속한 클래스를 또 상속할 수도 있음
상속과 생성자
복잡도의 증가
하위 클래스가 호출될 때 자동으로 상위 클래스의 기본 생성자를 호출하게 된다. 상위 클래스의 생성자가 매개변수를 포함한다면 오류 발생
-> 상위 클래스에 기본 생성자를 추가 (매개변수 없는)
super : 상위 클래스를 가리킴
class SubstractionableCalculator extends Calculator {
public SubstractionableCalculator(int left, int right) {
super(left, right); //상위 클래스의 생성자를 호출
}
public void substract() {
System.out.println(this.left - this.right);
}
}
Overriding
상위 클래스를 상속받았을때 메소드를 수정하려면-?
class Calculator {
int left, right;
public void setOprands(int left, int right) {
this.left = left;
this.right = right;
}
public void sum() {
System.out.println(this.left + this.right);
}
public void avg() {
System.out.println((this.left + this.right) / 2);
}
}
class SubstractionableCalculator extends Calculator {
public void sum() {
System.out.println("실행 결과는 " +(this.left + this.right)+"입니다.");
}//메소드 수정
public void substract() {
System.out.println(this.left - this.right);
}
}
리턴 형식을 바꿈 -> 에러!!
public int avg() {
return (this.left + this.right)/2;
}
오버라이딩 조건
-메소드의 이름
-메소드 매개변수의 숫자와 데이터 타입 그리고 순서
-메소드의 리턴 타입
Overloading
public void setOprands(int left, int right){
System.out.println("setOprands(int left, int right)");
this.left = left;
this.right = right;
}
public void setOprands(int left, int right, int third){
System.out.println("setOprands(int left, int right, int third)");
this.left = left;
this.right = right;
this.third = third;
}
c1.setOprands(10,20);
c1.setOprands(10, 20, 30);
//매개변수의 수를 다르게 해서 호출 가능
//매개변수의 숫자에 따라 같은 이름의 서로 다른 메소드를 호출한다
이름은 같지만 시그니처는 다른 메소드를 중복으로 선언할 수 있는 방법
-> 메소드 오버로딩
오버로딩의 규칙
-매개변수에 따라 서로 다른 메소드로 구별된다
-매개변수는 같지만 리턴타입이 다르면 오류!!
*메소드를 호출할 때 전달되는 인자의 데이터 타입에 따라서 어떤 메소드를 호출할 지 자바가 판단!!
*메소드의 반환값은 메소드를 호출하는 시점에서 전달되지 않는 정보이기 때문에 오버로딩할 수 없다
상속한 뒤에 오버로딩도 가능
오버로딩과 오버라이딩
오버로딩 - 다른 매개변수를 받는 메소드를 여러 개 만들 수 있다
오버라이딩 - 부모 클래스의 메소드를 다르게 동작하도록 수정할 수 있다
class Calculator{
int[] oprands;
public void setOprands(int[] oprands){
this.oprands = oprands;
}
public void sum(){
int total = 0;
for(int value : this.oprands){
total += value;
}
System.out.println(total);
}
public void avg(){
int total = 0;
for(int value : this.oprands){
total += value;
}
System.out.println(total/this.oprands.length);
}
}
public class CalculatorDemo {
public static void main(String[] args) {
Calculator c1 = new Calculator();
c1.setOprands(new int[]{10,20});
c1.sum();
c1.avg();
c1.setOprands(new int[]{10,20,30});//c1.setOprands(new {10,20,30});
c1.sum();
c1.avg();
}
}
'JAVA' 카테고리의 다른 글
JAVA 플레이 그라운드 (0) | 2019.06.22 |
---|---|
자바 - 파일 입출력 (0) | 2019.05.30 |
자바 - 나무보다 숲을 보자(3) (0) | 2019.05.24 |
자바 - 나무보다 숲을 보자(3) (0) | 2019.05.22 |
자바 - 나무보다 숲을 보자(1) (0) | 2019.05.19 |