상태와 행위로 이루어진 객체를 만드는것.
--> 마치 레고 블럭처럼 조립해서 하나의 큰 프로그램을 만듦.
추상화
--> 복잡한 현실을 소프트웨어적으로 구현하는 행위 (ex.지하철맵)
은닉화/캡슐화
--> 내부의 동작방법을 단단한 케이스(객체)안에 숨기고 사용자에게는 그 부품의 사용법만을 노출.
클래스/인스턴스/객체
1) 중복의 제거: 메소드사용
package test;
public class javatest {
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);
}
}
2) 객체화
--> 객체는 변수와 메소드의 집합인 하나의 "프로그램"이라고 여기자.
package test;
class Calculator {
int left,right;
public void setOperands(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 CalculatorDemo {
public static void main(String[] args) {
Calculator c1 = new Calculator();
c1.setOperands(10,20);
c1.sum();
c1.avg();
Calculator c2 = new Calculator();
c2.setOperands(20,40);
c2.sum();
c2.avg();
}
}
--> this : 클래스 Calculator의 객체 'c1'을 뜻함.
따라서 this.left와 this.right는 class를 생성할 때 초입에서 생성한 int left , int right 변수를 의미한다.
Ex) c1.setOperands(10,20)에서 10,20은 각각 setOperands함수의 파라미터(int left , int right)안에 할당이되고 this.left,right는 class의 전역변수인 int left,right가 되는것이다.
3) 클래스변수
인스턴스 - 클래스맴버
변수,메소드 - 인스턴스맴버
class Calculator {
static double PI = 3.14;
int left,right;
package test;
class Calculator {
static double PI = 3.14; (클래스맴버)
static int base = 0; (클래스맴버)
int left,right;
public void setOperands(int left, int right) {
this.left = left;
this.right = right;
}
public void sum() {
System.out.println(this.left + this.right + base);
}
}
public class CalculatorDemo {
Calculator c1 = new Calculator();
c1.setOperands(20,40);
c1.sum(); ==> '60'출력
Calculator c2 = new Calculator();
c2.setOperands(30,50);
c2.sum(); ==> '80'출력
Calculator.base = 10;
cl.sum(); ==> '70'출력
c2.sum(); ==> '90'출력
}
4) 클래스 메소드
package test;
class Calculator {
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 CalculatorDemo {
public static void main(String[] args) {
Calculator.sum(10,20);
Calculator.avg(10,20);
Calculator.sum(20,40);
Calculator.avg(20,40);
}
}
5) 타입별 비교
package test;
class C1 {
static int static_variable = 1; //static이 붙어있으므로 클래스변수.
int instance_variable = 2; //static이 없으므로 instance 변수.
static void static_static() { //클래스메소드(static)가 클래스변수(static)를 호출할 때.
System.out.println(static_variable);
}
static void static_instance() {
//클래스 메소드에서는 인스턴스 변수에 접근 할 수 없다.
//System.out.println(instance_variable);
}
void instance_static() { //인스턴스 메소드 (static이 없는것)
//인스턴스 메소드에서는 클래스멤버에 접근가능.
System.out.println(static_variable);
}
void instance_instance() { //인스턴스 메소
System.out.println(instance_variable);
}
public class ClassDemo {
public static void main(String[] args) {
C1 c = new C1() ;
c.static_static() ; //인스턴스변수는 클래스메소드에 접근가능.
c.static_instance() ; //인스턴스변수는 static메소드에 접근불가.
//static메소드와 class static메소드는 다름.
//인스턴스변수가 class static메소드에는 접근가능하지만 단순 static메소드에는 접근불가.
c.instance_static(); //인스턴스변수는 static클래스변수에 접근가능.
c.instance_instance(); // 인스턴스변수는 인스턴스메소드에 접근가능.
c1.static_static() ; //클래스자체(인스턴스아님)c1은 클래스메소드에 직접 접근가능.
c1.static_instance() ; //클래스c1은 static메소드에 접근불가.
c1.instance_static() ; // 클래스c1은 인스턴스가 아니므로 인스턴스메소드에 접근불가.
c1.instance_instance(); //클래스c1은 인스터스가 아니므로 인스턴스메소드에 접근불가.
}
}
}
6) 용어
인스턴스변수 -> Non-static Field
클래스변수 -> static Field
따라서 오른쪽 그림의 i는 전역변수이므로 main함수를 실행시킬때 a()함수역시 실행되고 a라는 함수에는 i가 0 이므로 for문의 i 즉 0 이 무한 출력되는것이다. 이것은 i가 전(지)역 변수이므로 모든 함수에 적용되는 변수이기 때문이다.
하지만 함수 a의 변수 i를 int i = 0; 으로 설정해주면 전역변수 int i 랑은 다른 int i다. 즉 a함수내에서 끝나는 지역변수이다.
이와 마찬가지로 for문에서 i 대신 int i = 0; 으로 설정시 i는 for문 '내'에서만 존재하는 i이므로 a함수의 i랑은 상관이 없다.
1)
public class javatest {
static void a() {
String title = "coding everybody";
}
public static void main(String[] args) {
a();
System.println(title);
-> title 출력불가능.
title은 지역변수이므로 main함수입장에서는 인지할 수 없음.
}
}
2)
public class javatest {
public static void main(String[] args) {
for(int i=0; i<5; i++) {
System.out.println(i);
}
System.out.println(i);
-> i 출력불가능 , i는 for문의 중괄호안에서만 존재.
}
}
3)
public class javatest {
static int i = 5;
static void a() {
int i = 10;
b();
}
static void b() {
System.out.println(i);
-> i는 함수b의 유효범위 내 존재하는 i로 값이 할당됨.
따라서 함수 b에 예를들어 지역변수 int i = 33; 이 선언되어있다면
33을 출력할것이고 지역변수가 없다면 전역변수를 끌어와 5를 출력할 것이다.
}
public static void main(String[] args) {
a();
}
}
class C {
int v = 10;
void m() {
int v = 20;
System.out.println(v);
System.out.println(this.v);
}
}
public class javatest {
public static void main(String[] args) {
C c1 = new C();
c1.m();
}
}
이와같은 상황에서는 전역변수vs지역변수 형태인데 이와같은 경우엔 지역변수가 이기므로 20을 출력한다.
System.out.println(this.v);
this -> 인스턴스에 대한 '전역'의 의미를 갖게됨. (10 출력)
class Calculator {
static double PI = 3.14;
int left, right;
public void setOperands(int _left , int _right) {
left = _left;
right = _right;
}
}
class Calculator {
int left, right;
//생성자
public Calculator(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 CalculatorDemo {
public static void main(String[] args) {
Calculator c1 = new Calculator(10,20);
c1.sum();
c1.avg();
}
}
}
setOperands와 같이 파라미터에 값을 할당하는 함수를 따로 만들지 않고도 클래스를 만들때부터 인자값을 줄 수 있도록 하기위해서 '생성자'(Constructor)를 만든다. 이때 주의점은 클래스명과 생성자의 이름이 완벽히 동일해야한다.
생성자는 그 어떠한 메소드보다 먼저 실행되므로 '초기화' 작업을 실행할 수 있다.
Cacluator c1 = new Calculator(10,20); 에서 new 뒤에 붙는 Calculator는 클래스가 아닌 생성자를 의미. 즉, new Calculator(생성자)를 이용해 인스턴스 클래스명이 Calculator인 인스턴스 c1을 만드는것이다.
class Calculator {
int left, right;
public Calculator(int left , int right) {
this.left = left;
this.right = right;
}
public void setOperands(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 SubtractionableCalculator extends Calculator {
pulbic void subtract () {
System.out.println(this.left - this.right);
}
}
public class CalculatorDemo {
SubtractionableCalculator c1 = new SubtractionableCalculator() ;
c1.setOperands(10,20);
c1.sum();
c1.avg();
c1.subtract();
}
}
또한 상속받은것을 재상속 받을 수 도 있음.
class MultiplicationableCalculator extends SubtractionableCalculator() {
public void Multiple() {
System.out.println(this.left * this.right);
}
}
public class Constructor {
public Constructor() {
public Constructor(int param1) {}
public static void main(String[] args) {
Constructor c = new Constructor() ;
}
}
}
class Calculator {
int left, right;
public Calculator(int left , int right) {
this.left = left;
this.right = right;
}
public void setOperands(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 SubtractionableCalculator extends Calculator(int left, int right) {
}
this.left = left;
this.right = right;
--> 지금은 상위클래스의 생성자와 하위클래스의 생성자가 동일. 즉, 중복된다.
따라서 하위클래스가 상위클래스의 생성자를 그대로 받고 싶으면
super(left, right); 라고 해준다.
pulbic void subtract () {
System.out.println(this.left - this.right);
}
}
부모가 가진 메소드를 자식이 나름대로의 변형을 통해 "재정의" 한다.
1)
class SubtractionableCalculator extends Calculator(int left, int right) {
}
this.left = left;
this.right = right;
public void subtract () {
System.out.println("실행 결과는 " + (this.left - this.right) + "입니다");
}
}
2)
class Calculator {
int left, right;
public Calculator(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 SubtractionableCalculator extends Calculator {
public int avg() {
return ((this.left - this.right) /2);
}
}
}
오버라이딩 만족조건:
1) 메소드 이름
2) 메소드 매개변수 숫자, 데이터타입 , 순서
3) 리턴타입이 모두 동일!
3)
public int avg() {
return ((this.left + this.right)/2);
}
class SubtractionableCalculator extends Calculator {
public int avg() {
return ((this.left - this.right) /2);
}
}
3)과 같은경우는 avg함수가 부모,자식클래스간에 동일하게 적용된다. 중복되므로 자식클래스에서 return super.avg(); 라고 하면 부모클래스의 메소드를 적용받을 수 있게된다.
public void sum(int a , int b ) {
System.out.println(a + b);
}
public void sum(int a , int b , int c) {
System.out.println(a+b+c);
}
class overloading {
void A() {System.out.println("void A()");}
void A(int arg1) {System.out.println("void is A(int arg1)");}
void A(String arg1) {System.out.println("void A(String arg1)");}
//int A() {System.out.println("void A()");}
-->리턴값이 다르므로 오버로딩 불가.
public static void main(String[] args) {
overloading od = new overloading() ;
od.A();
od.A(1);
od.A("I love you");
}
}
public class overloading2 extends overloading {
void A(Stirng arg1, Stirng arg2) {System.out.println("sub class: void A()");}
void A() {System.out.println("sub class: void A()");}
public static void main(String[] args) {
overloading2 od = new overloading2() ;
od.A();
od.A(1);
od.A("I love you");
od.A("I love you", "you too?");
}
}
package org.opentutorials.javatutorials.packages.example2;
import org.opentutorials.javatutorials.packages.example1.A;
-> 클래스A만 import (B는제외)
만약 모든 클래스를 소환하고 싶으면 '*' 사용
public class B {
public static void main(String[] args) {
A a = new A();
}
}