OOP (Object-Oriented Programming) 객체지향개념클래스, 객체, 메소드 514760-1 2016 년가을학기 9/29/2016 박경신 소프트웨어의생산성향상 컴퓨터산업발전에따라소프트웨어의생명주기 (life cycle) 단축 객체지향언어는상속, 다형성, 객체, 캡슐화등소프트웨어재사용을위한여러장치내장 소프트웨어의재사용과부분수정을통해소프트웨어를다시만드는부담을대폭줄임으로써소프트웨어의생산성이향상 실세계에대한쉬운모델링 과거 수학계산 / 통계처리를하는등의처리과정, 계산절차가중요 현재 컴퓨터가산업전반에활용 실세계에서발생하는일을프로그래밍 실세계에서는절차나과정보다일과관련된물체 ( 객체 ) 들의상호작용으로묘사하는것이용이 실세계의일을보다쉽게프로그래밍하기위한객체중심의객체지향언어탄생 실제세계는객체로이루어진다. Object-Oriented? 실제세계를모델링하여소프트웨어를개발하는방법
객체 (Object) 객체 (object) 는상태 (state) 와동작 (behavior) 을가짐. 객체의상태 (state) 는객체의속성임. 객체의동작 (behavior) 또는행동은객체가할수있는동작임. 상태는필드 (field) 로동작은메소드 (method) 로구현됨. 절차지향프로그래밍 vs OOP 절차지향프로그래밍 (Procedural Programming) 작업순서를표현하는컴퓨터명령집합 함수들의집합으로프로그램작성 객체지향프로그래밍 (Object Oriented Programming) 프로그램을실제세상에가깝게모델링 컴퓨터가수행하는작업을객체들간의상호작용으로표현 클래스혹은객체들의집합으로프로그램작성 절차지향적프로그래밍의실행절차 절차지향프로그래밍 vs OOP 객체지향의 3 대특징 캡슐화 (Encapsulation) 상속 (Inheritance) 다형성 (Polymorphism)
캡슐화 (Encapsulation) 캡슐화 (Encapsulation) 관련된데이터와알고리즘 ( 코드 ) 를하나의덩어리로묶는것 메소드 ( 함수 ) 와데이터를클래스내에선언하고구현 외부에서는공개된메소드의인터페이스만접근가능 외부에서는비공개데이터에직접접근하거나메소드의구현세부를알수없음 객체내데이터에대한보안, 보호, 외부접근제한 캡슐화 (Encapsulation) 자바객체의캡슐화 실세계의캡슐화 캡슐화와정보은닉 정보은닉이가능하기때문에업그레이드기쉽게가능 정보은닉 (information hiding) 은객체를캡슐로싸서객체의내부를보호하는하는것이다. 즉객체의실제구현내용을외부에감추는것임. 상속 (Inheritance) 상속 (Inheritance): 이미작성된클래스 ( 부모클래스 ) 를이어받아서새로운클래스 ( 자식클래스 ) 를생성하는기법 기존의코드를재활용하기위한기법 상속의개념
상속 (Inheritance) 다형성 (Polymorphism) 상속 상위클래스의특성을하위클래스가물려받음 상위클래스 : 수퍼클래스, 하위클래스 : 서브클래스 서브클래스 수퍼클래스코드의재사용 새로운특성추가가능 자바는클래스다중상속없음 인터페이스를통해다중상속과같은효과얻음 다형성 (Polymorphism) 동일한이름으로많은상황에대처하는기법 자바의다형성사례 슈퍼클래스의메소드를서브클래스마다다르게구현하는메소드오버라이딩 (overriding) 클래스와객체 클래스 객체의속성과행위선언 객체의설계도혹은틀 객체 클래스의틀로찍어낸실체 사례 메모리공간을갖는구체적인실체 클래스를구체화한객체를인스턴스 (instance) 라고부름 객체와인스턴스는같은뜻으로사용 클래스 : 소나타자동차, 클래스 : 벽시계, 클래스 : 책상, 객체 : 출고된실제소나타 100대객체 : 우리집벽에걸린벽시계들객체 : 우리가사용중인실제책상들 클래스와객체 이름 최승희 직업 의사 나이 45 성별 여 혈액형 A 클래스 : Person 이름, 직업, 나이, 성별, 혈액형밥먹기, 잠자기, 말하기, 걷기 이름 이미녀 직업 골프선수 나이 28 성별 여 혈액형O 이름 김미남 직업 교수 나이 47 성별 남 혈액형AB 객체 : 최승희 객체 : 이미녀 객체 : 김미남
클래스구조 클래스선언 클래스접근권한, public 다른클래스들에서이클래스를사용하거나접근할수있음을선언 class Person Person 이라는이름의클래스선언 클래스는 { 로시작하여 로닫으며이곳에모든필드와메소드구현 필드 (field) 값을저장할멤버변수 멤버변수혹은필드라고함 필드의접근지정자 public 필드를다른클래스의메소드에서접근할수있도록공개한다는의미 메소드 (method) 메소드는함수이며객체의행위를구현 메소드의접근지정자 public 메소드를다른클래스의메소드에서호출할수있도록공개한다는의미 생성자 (constructor) 클래스의이름과동일한메소드 클래스의객체가생성될때만호출되는메소드 객체생성 객체생성및사용예 객체생성 new 키워드를이용하여생성 new 는객체의생성자호출 객체생성과정 1. 객체에대한레퍼런스변수선언 2. 객체생성 public static void main (String args[]) { Person aperson; // 1. 레퍼런스변수 aperson 선언 aperson = new Person(" 김미남 "); // 2. Person 객체생성 aperson.age = 30; // 객체멤버접근 int i = aperson.age; // 30 String s = aperson.getname(); // 객체메소드호출
객체의활용 객체의멤버접근 : 객체레퍼런스. 멤버 객체의필드에값대입 public class ClassExample { public static void main (String args[]) { Person aperson = new Person(" 홍길동 "); aperson.age = 30; int i = aperson.age; String s = aperson.getname(); 객체의필드에서값읽기 객체의메소드호출 Ex: Goods 클래스 public class Goods { String name; // 상품이름 int price; // 상품가격 int numberofstock; // 재고수량 int numberofsold; // 팔린수량 public static void main(string[] args) { Goods camera = new Goods(); camera.name = "Nikon"; camera.price = 400000; camera.numberofstock = 30; camera.numberofsold = 50; 상품이름 :Nikon 상품가격 :400000 재고수량 :30 팔린수량 :50 System. out.println(" 상품이름 :" + camera.name); System.out.println(" 상품가격 :" + camera.price); System.out.println(" 재고수량 :" + camera.numberofstock); System.out.println(" 팔린수량 :" + camera.numberofsold); Ex: Car 클래스 public class Car { String color; // 색상 int speed; // 속도 int gear; // 기어 @Override public String tostring() { return "Car [color=" + color + ", speed=" + speed + ", gear=" + gear + "]"; void setcolor(string c) { color = c; void speedup() { speed = speed + 10; void speeddown() { speed = speed - 10; void changegear(int g) { gear = g; public class CarTest { public static void main(string[] args) { Car mycar = new Car(); mycar.setcolor( red ); mycar.changegear(1); mycar.speedup(); System.out.println(myCar); Car [color=red, speed=10, gear=1] 메소드형식 메소드 메소드는 C/C++ 의함수와동일 자바의모든메소드는반드시클래스안에있어야함 ( 캡슐화원칙 ) 메소드구성형식 접근지정자 public. private, protected, 디폴트 ( 접근지정자생략된경우 ) 리턴타입 메소드가반환하는값의데이터타입
인자전달 기본타입 자바의인자전달방식 (Parameter Passing) 값에의한호출 (call by value) 기본타입의값을전달하는경우 값이복사되어전달 메소드의매개변수가변경되어도호출한실인자값은변경되지않음 인자전달 레퍼런스타입 자바의인자전달방식 객체혹은배열을전달하는경우 객체나배열의레퍼런스만전달 객체혹은배열이통째로복사되어전달되는것이아님 메소드의매개변수와호출한실인자가객체나배열을공유하게됨 아주중요!! 객체배열 객체배열생성및사용 27
객체배열선언과생성사례 public static void main(string [] args) { Person[] pa; pa = new Person[10]; for(int i=0;i<pa.length; i++) { pa[i] = new Person(); pa[i].age = 30 + i; for(int i=0;i<pa.length;i++) System.out.print(pa[i].age+" "); 30 31 32 33 34 35 36 37 38 39 Ex: 객체배열생성 import java.util.scanner; public class GoodsArray { public static void main(string[] args) { Goods [] goodsarray; goodsarray = new Goods [3]; Scanner s = new Scanner(System.in); for(int i=0; i<goodsarray.length; i++) { String name = s.next(); int price = s.nextint(); int n = s.nextint(); int sold = s.nextint(); goodsarray[i] = new Goods(name, price, n, sold); for(int i=0; i<goodsarray.length; i++) { System.out.print(goodsArray[i].getName()+" "); System.out.print(goodsArray[i].getPrice()+" "); System.out.print(goodsArray[i].getNumberOfStock()+" "); System.out.println(goodsArray[i].getSold()); Ex: 객체배열생성 class Goods { private String name; private int price; private int numberofstock; private int sold; Goods(String n, int p, int nstack, int s) { name = n; 콜라 500 10 20 price = p; 사이다 1000 20 30 numberofstock = nstock; 맥주 2000 30 50 sold = s; 콜라 500 10 20 사이다 1000 20 30 String getname() {return name; 맥주 2000 30 50 int getprice() {return price; int getnumberofstock() {return numberofstock; int getsold() {return sold; 매개변수에배열이전달되는경우 2 3 4 5 6 매개변수에배열의레퍼런스만전달
Ex: 배열의전달 public class ArrayParameter { static void replacespace(char a[]) { for (int i = 0; i < a.length; i++) if (a[i] == ' ') a[i] = ','; static void printchararray(char a[]) { for (int i = 0; i < a.length; i++) System.out.print(a[i]); System.out.println(); public static void main (String args[]) { char c[] = {'T','h','i','s',' ','i','s',' ','a',' ','p','e','n','c','i','l','.'; printchararray(c); replacespace(c); printchararray(c); char 배열을메소드의인자로전달하여배열속의공백 (' ') 문자를, 로대치하는프로그램을작성하라. a T h i s i s a p e n c i l. c for (int i = 0; i < a.length; i++) if (a[i] == ' ') a[i] = ',';, This is a pencil. This,is,a,pencil. replacespace() main() 메소드오버로딩 오버로딩 (Overloading) 한클래스내에서두개이상의이름이같은메소드작성 메소드이름이동일하여야함 매개변수의개수가서로다르거나, 타입이서로달라야함 리턴타입은오버로딩과관련없음 // 메소드오버로딩이성공한사례 class MethodOverloading { public int getsum(int i, int j) { return i + j; public int getsum(int i, int j, int k) { return i + j + k; public double getsum(double i, double j) { return i + j; // 메소드오버로딩이실패한사례 class MethodOverloadingFail { public int getsum(int i, int j) { return i + j; public double getsum(int i, int j) { return (double)(i + j); 오버로딩된메소드호출 this 레퍼런스 this 란? 현재실행되는메소드가속한객체에대한레퍼런스 컴파일러에의해자동선언 : 별도로선언할필요없음 class Samp { int id; public Samp(int x) { id = x; public void set(int x) { id = x; public int get() {return id; class Samp { int id; public Samp(int x) { this.id = x; public void set(int x) { this.id = x; public int get() {return id;
this 가필요한경우 this 에대한이해 this 의필요성 객체의멤버변수와메소드변수의이름이같은경우 다른메소드호출시객체자신의레퍼런스를전달할때 메소드가객체자신의레퍼런스를반환할때 class Samp { int id; // 매개변수이름과필드의이름이같을때 public Samp(int id) { this.id = id; public void set(int id) { this.id = id; public int get() {return this.id; public Samp me() { return this; // 자신의레퍼런스를반환할때 객체의치환 * 객체의치환은객체가복사되는것이아니며레퍼런스가복사된다. 필드의초기화 선언과동시에초기화가능 생성자를사용하는방법 -> 다음장에서학습 ob1.id=4 ob2.id=4
생성자개념 생성자 - 객체가생성될때초기화를위해실행되는메소드 생성자 생성자의특징 생성자는메소드 생성자이름은클래스이름과동일 생성자는 new 를통해객체를생성할때만호출됨 생성자도오버로딩하여여러개작성가능 생성자는리턴타입을지정할수없음 생성자는하나이상선언되어야함 개발자가생성자를작성하지않았으면컴파일러에의해자동으로기본생성자가선언됨 기본생성자를디폴트생성자 (default constructor) 라고도함 생성자정의와생성자호출 기본생성자 기본생성자 (default constructor) 클래스에생성자가하나도선언되지않은경우 컴파일러에의해자동으로생성 매개변수없는생성자 아무작업없이단순리턴 디폴트생성자라고도부름 class DefaultConstructor{ int x; public void setx(int x) {this.x = x; public int getx() {return x; public static void main(string [] args) { DefaultConstructor p = new DefaultConstructor(); p.setx(3); 개발자가작성한코드
기본생성자 class DefaultConstructor{ int x; public void setx(int x) {this.x = x; public int getx() {return x; public DefaultConstructor() { public static void main(string [] args) { DefaultConstructor p= new DefaultConstructor(); p.setx(3); 컴파일러가자동으로기본생성자를삽입한코드 컴파일러에의해자동삽입된기본생성자 기본생성자가자동생성되지않는경우 클래스에생성자가하나라도존재하면기본생성자가자동삽입되지않음 class DefaultConstructor{ int x; public void setx(int x) {this.x = x; public int getx() {return x; 컴파일러가기본생성자를자동생성하지않음 public DefaultConstructor() { public DefaultConstructor(int x) { this.x = x; public static void main(string [] args) { DefaultConstructor p1= new DefaultConstructor(3); int n = p1.getx(); DefaultConstructor p2= new DefaultConstructor(); p2.setx(5); 컴파일오류. 해당하는생성자가 없음!!! this(), 생성자에서다른생성자호출 this() 생성자호출 같은클래스의다른생성자호출 생성자내에서만사용가능 다른메소드에서는사용불가 반드시생성자코드의제일처음에수행 public class Book { String title; String author; int ISBN; public Book(String title, String author, int ISBN) { this.title = title; this.author = author; this.isbn = ISBN; public Book(String title, int ISBN) { this(title, "Anonymous", ISBN); public Book() { this(null, null, 0); System.out.println(" 생성자가호출되었음 "); title = "Holy Bible" author = "Anonymous" ISBN = 1 title = "Holy Bible" ISBN = 1 public static void main(string [] args) { Book javabook = new Book("Java JDK", " 황기태 ", 3333); Book holybible = new Book("Holy Bible", 1); Book emptybook = new Book(); this() 사용실패예 public Book() { System.out.println(" 생성자가호출되었음 "); this(null, null, 0); // 생성자의첫번째문장이아니기때문에컴파일오류
객체의소멸과가비지 객체소멸 new 에의해생성된객체메모리를자바가상기계로되돌려주는행위 소멸된객체공간은가용메모리에포함 자바응용프로그램에서임의로객체소멸할수없음 객체소멸은자바가상기계의고유한역할 자바개발자에게는매우다행스러운기능 C/C++ 에서는할당받은객체를개발자가프로그램내에서삭제해야함 C/C++ 의프로그램작성을어렵게만드는요인 가비지 (Garbage) 가비지 (Gabage) : 가리키는레퍼런스가하나도없는객체 더이상접근하여사용할수없게되었음 가비지켈렉션 (Gabage Collection) 자바가상기계의가비지컬렉터가자동으로가비지를수집하여반환 설정자와접근자 설정자 (mutator) 필드의값을설정하는메소드 setxxx() 형식 접근자 (accessor) 필드의값을반환하는메소드 getxxx() 형식 접근자와변경자메소드만을통하여필드에접근한다. 설정자와접근자 Ex: 설정자 (set) 와접근자 (get) 현재자동차의색상는 red 현재자동차의속도는 100 현재자동차의기어는 1
설정자와접근자는왜사용하는가? 설정자에서매개변수를통하여잘못된값이넘어오는경우, 이를사전에차단할수있음. 필요할때마다필드값을계산하여반환할수있음. 접근자만을제공하면자동적으로읽기만가능한필드를만들수있음. 지역변수 메소드안에선언 메소드의매개변수도지역변수의일종 주의 가비지사례 지역변수를초기화하지않고사용하면오류 Exception in thread "main" java.lang.error: Unresolved compilation problems: The local variable sum may not have been initialized...
객체의생성 참조값을복사한다면 두개의참조변수가하나의객체를가리킬수있음. 객체의소멸 객체의소멸
Ex: 가비지발생 다음소스에서언제가비지가발생하는지설명하라. public class GarbageEx { public static void main(string[] args) { String a = new String("Good"); String b = new String("Bad"); String c = new String("Normal"); String d, e; a = null; d = c; c = null; 가비지컬렉션 가비지컬렉션 자바에서가비지자동회수 가용메모리공간으로확보 가비지컬렉터 (garbage collector) 에의해자동수행 개발자에의한강제가비지컬렉션 System 또는 Runtime 객체의 gc() 메소드호출 System.gc(); // 가비지컬렉션작동요청 이코드는자바가상기계에강력한가비지컬렉션요청 그러나자바가상기계가가비지컬렉션시점을전적으로판단 접근지정자이해 클래스접근지정자 클래스앞에올수있는접근지정자 public 접근지정자 public class Person { 다른모든클래스가접근가능 접근지정자생략 (default 접근지정자 ) class Person { package-private 라고도함 같은패키지내에있는클래스에서만접근가능 같은디렉토리에있는클래스끼리접근가능
멤버접근지정자 멤버접근지정자의이해 디폴트 (default) 멤버 같은패키지내의다른클래스만접근가능 public 멤버 패키지에관계없이모든클래스에서접근가능 private 멤버 클래스내에서만접근가능 상속받은하위클래스에서도접근불가 protected 멤버 같은패키지내의다른모든클래스에서접근가능 상속받은하위클래스는다른패키지에있어도접근가능 public 접근지정사례 private 접근지정사례 멤버접근지정자의이해 멤버접근지정자의이해 디폴트접근지정사례 protected 접근지정사례
Ex: 접근지정자의사용 다음의소스를컴파일해보고오류가난이유를설명하고오류를수정하시오. class Sample { public int a; private int b; int c; public class AccessEx { public static void main(string[] args) { Sample aclass = new Sample(); aclass.a = 10; aclass.b = 10; aclass.c = 10; Sample 클래스의 a 와 c 는각각 public, default 지정자로선언이되었으므로, 같은패키지에속한 AccessEx 클래스에서접근가능 b 는 private 으로선언이되었으므로 AccessEx 클래스에서접근불가능 Ex: 결과 class Sample { 오류가수정된소스 public int a; private int b; int c; public int getb() { return b; public void setb(int value) { b = value; public class AccessEx { public static void main(string[] args) { Sample aclass = new Sample(); aclass.a = 10; aclass.setb(10); aclass.c = 10; private 접근지정자를갖는멤버 b 를위해클래스내부에 getb()/setb() 메소드만들어접근 static 멤버와 non-static 멤버 non-static 멤버와 static 멤버의차이 non-static 멤버의특성 공간적 - 멤버들은객체마다독립적으로별도존재 인스턴스멤버라고도부름 시간적 - 필드와메소드는객체생성후비로소사용가능 비공유의특성 - 멤버들은여러객체에의해공유되지않고 배타적 static 멤버란? 객체를생성하지않고사용가능 클래스당하나만생성됨 클래스멤버라고도부름 객체마다생기는것이아님 특성 class StaticSample { int n; // non-static 필드 void g() {... // non-static 메소드 static int m; // static 필드 static void f() {... // static 메소드 공간적특성 - static 멤버들은클래스당하나만생성. 시간적특성 - static 멤버들은클래스가로딩될때공간할당. 공유의특성 - static 멤버들은동일한클래스의모든객체에의해공유
static 멤버를객체의멤버로접근하는사례 74 static 의활용 전역변수와전역함수를만들때활용 자바의캡슐화원칙지킴 다른클래스에서공유하는전역변수나전역함수도반드시클래스내부에구현해야함 static 멤버를가진클래스사례 java.lang.math 클래스 JDK와함께배포되는 java.lang.math 클래스 모든필드와메소드가 public static으로선언 다른모든클래스에서사용할수있음 public class Math { // 잘못된사용법 public static int abs(int a); //Math() 생성자는 private public static double cos(double a); //Math m = new Math() public static int max(int a, int b); //int n = m.abs(-5) public static double random();... // 바른사용법 int n = Math.abs(-5); static 메소드의제약조건 1 static 메소드는오직 static 멤버만접근가능 객체가생성되지않은상황에서도 static 메소드는실행될수있기때문에, non-static 메소드와필드사용불가 non-static 메소드는 static 멤버사용가능
static 메소드의제약조건 2 static 메소드는 this 사용불가 static 메소드는객체가생성되지않은상황에서도호출이가능하므로, 현재객체를가리키는 this 레퍼런스사용할수없음 Ex: static 을이용한달러와우리나라원화사이의변환예제 class CurrencyConverter { private static double rate; // 한국원화에대한환율 public static double todollar(double won) { return won/rate; // 한국원화를달러로변환 public static double tokwr(double dollar) { return dollar * rate; // 달러를한국원화로변환 public static void setrate(double r) { rate = r; // 환율설정. KWR/$1 public class StaticMember { public static void main(string[] args) { static 필드와메소드를이용하여달러와한국원화사이의변환을해주는환율계산기를만들어보자. 백만원은 892.0606601248885 달러입니다. 백달러는 112100.0 원입니다. CurrencyConverter.setRate(1121); // 미국달러환율설정 System.out.println(" 백만원은 " + CurrencyConverter.toDollar(1000000) + " 달러입니다."); System.out.println(" 백달러는 " + CurrencyConverter.toKWR(100) +" 원입니다."); final 클래스와메소드 final 클래스 - 더이상클래스상속불가능 final class FinalClass {... class DerivedClass extends FinalClass { // 컴파일오류... final 메소드 - 더이상오버라이딩불가능 final 필드 final 필드, 상수선언 상수를선언할때사용 class SharedClass { public static final double PI = 3.141592653589793; 상수필드는선언시에초기값을지정하여야한다 상수필드는실행중에값을변경할수없다 상수는 static 으로선언하는것이바람직함 public class SuperClass { protected final int finalmethod() {... class DerivedClass extends SuperClass { protected int finalmethod() {... // 컴파일오류, 오버라이딩할수없음
final 필드 String 클래스의메소드 public class FinalFieldClass { static final int ROWS = 10; // 상수정의, 이때초기값 (10) 을반드시설정 void f() { int [] intarray = new int [ROWS]; // 상수활용 //ROWS = 30; // 컴파일오류발생, final 필드값을변경할수없다. 문자열의결합 두개의문자열은 + 연산자를이용하여결합될수있다. String subject = "Money"; String other = " has no value if it is not used"; String sentence = subject + other; 숫자를문자열로변환 int x = 20; System.out.println(" 결과값은 + x); // 결과값은 20 이출력된다. String answer = "The answer is " + 100; // The answer is 100" "Money has no value if it is not used" 결과값은 20 The answer is 100