프로그래밍 자바(언어)
정처기_ part4_ 프로그래밍 언어 활용
객체지향 프로그래밍
=> 내가 기억해야 할 것 요약!
(1) 객체지향 프로그래밍
1) 객체지향기술
2) 객체지향 개발절차
3) java 언어
4) 파이썬 언어
(1)객체지향 프로그래밍
3) java 언어
1) 클래스와 객체
클래스와 객체)
java에서의 클래스 : 자바는 모든 코드가 클래스
//Circle 클래스 정의
class Circle{
...
}
//HelloWorld 클래스 정의(프로그램 시작 지점)
public class HelloWorld{
public static void main(String[] args){
...
}
}
main메소드를 포함하는 클래스를 가장 먼저 실행(main 메소드가 프로그램의 시작지점!)
멤버(member) : 클래스에 포함되는 요소
데이터는 객체생성을 통해 확보
클래스 구성)
멤버 변수 : 객체가 가지는 모든 상태&수치&성질, C언어에서의 구조체(사용자 정의 자료형)과 유사, 다른 객체에서 접근할 수 없도록(정보 은닉)하여 사이드 이펙트를 최소화
멤버 메소드 : 객체에서 발생하는 모든 연산&제어&요청행위, C언어에서의 함수와 유사
//Circle 클랫 정의
class Circle
{ // 멤버 변수 정의
double pi - 3.14;
double radius;
// 멤버 메소드 정의
void volume(){
// 원의 부피 출력
System.out.println(radius * radius * pi);
}
}
자바 출력문 3가지 : println(줄바꿈까지), print(일반출력), printf(서식지정가능출력(=c언어))
접근 지정(제한)자)
정의 : 클래스 내 멤버들의 (외부) 접근 수준을 결정(정보은닉)하는 토큰, 프로그램-패키지-하위 클래스-자신의 클래스 순
종류 :
프로그램>패키지>클래스>하위클래스&자기 자신의 클래스
=>
멤버들을 나(클래스)만 사용?-> private(외부 접근 막기)
나를 상속 받는 하위 클래스까지만 사용?->protected
패키지 내 모든 클래스들이 접근->default(생략)
프로그램 전체에서 접근할 수 있게 할때->public
public : 프로그램 내 모든 객체에서 접근 가능
default(생략) : 같은 패키지 안에서만 접근 가능
protected : 자신과 하위 클래스에서만 접근 가능
private : 자신의 클래스에서만 접근 가능
// 접근 지정자를 생략하면 default로 인식
class Circle
{
private double pi = 3.14; //멤버 변수는 외부 접근이 불가능
private douvle radius;
void volume(){ //같은 패키지에서만 접근 가능
System.out.println(radius * radius * pi);
}
public void set_radius(double r){ //private멤버 접근을 위한 public메소드 정의
rarius = r;
}
}
코드 설명: 멤버 변수는 private로 설정해서 외부접근 막고
대신, public 메소드를 하나 만들어서 클래스 내부에서 변수에 값을 할당 할 수 있도록 함
-> 이는 절차(메소드)를 알고있는 객체에서만 멤버 변수에 접근->사이드 이펙드 발생 최소화 가능
생성자(Constructor) 메소드)
메소드 중에는 자신이 속한 클래스명과 이름이 동일하고, 리턴타입이 없는 특수 메소드
정의 :
클래스 내부에 존재, 객체가 생성 시 자동으로 실행(딱한번), 객체가 생성 될 때 외에는 별도로 실행 불가, 정의x면 자바에서 자동 생성, 객체 생성시 멤버 변수 초기화 처리, 생성자 메소드명은 클래스명과 동일, 리턴타입 없음.
this : 클래스 자신에 포함된 멤버 변수에 접근하기 위한 토큰, 이름이 동일한 다른 지역 변수와 구분을 위한 사용
Overloading : 동일한 이름을 가진 여러 메소드를 사용하는 기술, 메소드의 인수 유형과 개수의 차이로 각 메소드를 구별, 생성자 메소드 뿐 아니라 모든 메소드에 적용 가능( 같은 메소드명으로 서로 다른 기능을 정의)
Class Circle
{
private double pi = 3.14;
private double radius;
// 실수 인수 전달하여 객체 생성시 자동으로 실행
Circle(douvle radius){
this.radius = radius;
System.out.println("객체가 생성되었습니다.");
}
// 인수 전달 없이 객체 생성시 자동으로 실행
Circle(){
this.radius = 3.0;
System.out.println("기본객체가 생성되었습니다.");
}
}
Public class HelloWorld{
public static void main(String[] args){
Circle c1 = new Circle(5.0);
Circle c2 = new Circle();
}
}
this가 붙으면 멤버변수, 안붙은거는 매개변수나 지역변수
자바에서는 메소드명이 같아도 매개변수의 개수나 타입이 다르면 사용이 가능->오버로딩
인수를 넘기지 않고 객체를 생성하게 되면 아래에 있는 생성자가 호출-> radius가 3.0이 할당, 객체가 생성됨.
객체 생성)
인스턴스 생성 : Circle 클래스의 인스턴스를 생성하려면 Circle타입의 객체를 담을 수 있는 객체 변수가 필요
변수가 생성되면 new 키워드로 인스턴스 생성(아래코드에서는 3개의 인스턴스를 생성중)
새로운 객체를 생성하여 적절한 타인의 변수에 할당, new 키워드를 이용하여 인스턴스를 생성->생성자 호출, 일반적으로 인스턴스의 타입과 객체 변수의 타입이 동일.
객체의 멤버 접근 :
객체변수와 점(.)을 이용. 접근 지정자에 따라 직접 접근이 어려울 수 있음, 멤버 변수에 static키워드를 붙여 생성하면, 모든 객체가 공유하는 데이터 생성 가능 (물론, 접근 지정자가 private이면 접근 불가능!)
class Circle
{
private double pi = 3.14;
private double radius;
private static int cnt = 0;
Circle(double radius){
this.radius = radius;
this.cnt++;
System.out.println(this.cnt + "번 객체가 생성되어습니다.");
}
void created_cnt(){
System.out.println("총 " + this.cnt + "개 도형이 존재합니다.");
}
}
public class Helloworld{
public static void main(String[] args){
// Circle 인스턴스 생성
Circle c1 = new Circle(5.0);
Circle c2 = new Circle(4.0);
Circle c3 = new Circle(3.0);
created_cnt();
}
}
모든 객체는 고유의 데이터를 가짐, 모든 객체가 공유하는 데이터가 필요할 땐 static을 붙이기
static 키워드가 붙은 변수는 클래스가 사용되는 순간 생성되어 모든 객체가 접근하여 사용.
위 코드에서 Circle 생성자에서 static 변수를 증가(static이 없었으면 cnt는 각 객체마다 존재하여 1이 할당, static이기 때문에 출력하면 결과로 3이 나옴.
상속)
1. 상위 클래스
상위 클래스는 대부분의 속성을 하위 클래스에게 상속, 여러 하위 클래스가 사용할 공통된 속성을 구현, 상위 클래스 단독으로 인스턴스를 생성 가능
2. 하위 클래스
상속 받은 상위 클래스의 대부분의 속성을 포함, extends키워드를 사용하여 상속받을 상위 클래스를 지정, 상위 클래스의 메소드를 재사용, 재정의하여 사용
3. 오버라이딩(Overriding)
사우이 클래스의 메소드를 재정의하여 사용하는 기술, 상위 클래스와 동일한 메소드명과 매개변수를 지정
// 에스프레소 클래스
class Espresso{
int espresso = 20;
void recipe(){
System.out.println("에스프레소 " + espresso + "ml");
}
}
// 에스프레소 클래스를 상속 받은
// 아메리카노 클래스
// 아래는 water변수 밖에 없지만 에스프레소클래스를 상속 받아서 espresso변수도 사용가능!
class Americano extends Espresso{
int water = 80;
// recipe()메소드역시 사용 가능, 그런데 내용을 바꾸고 싶으면 같은 형식으로 메소드를 재정의
// 아래 recipe()은 재정의해놓은 것!
// 이렇게 하면 에스프레소 인스턴스의 레시피 메소드는 에스프레소 용량만 나오게 되고,
// 아메리카노 인스턴스의 레시피 메소드는 에스프레소와 물이 나옴
void recipe(){
// Espresso 클래스의 water멤버를 사용할 수 있다.
System.out.println("에스프레소 " + espresso + "ml + 물" + water + "ml");
}
}
public class HelloWorld{
public static void main(String[] args){
Espresso e1 = new Espresso();
e1.recipe();
Americano a1 = new Americano();
상위클래스를 만들고 하위클래스에서 extends키워드로 상속 받음. 상속 받은 하위 클래스는 상위 클래스의 모든 멤버를 사용하는 객체를 생성, 오버로딩을 통해 메소드를 재정의해서 사용가능
추상 클래스)
상속을 하지 않고서는 사용할 수 없는, 구체화를 위한 틀(frame)만을 제공
개념 :
클래스의 체계적인 설계를 위해 사용하는 클래스, 선언부만 있고, 구현부가 없는 추상 메소드를 하나 이상 포함. 반드시 하위클래스에서 상속하여 추상 메소드를 오버라이딩해야 인스턴스 생성이 가능. 상속된 클래스에서도 구현되지 않은 ㅊ상 메소드가 있다면 그 역시 추상 클래스이므로 인스턴스 생성이 불가능. 각각의 하위 클래스에서 수행되는 유사한 기능을 하나의 이름으로 통일 가능
구현 :
abstract키워드를 사용하여 클래스와 메소드를 구현
메소드의 구현부(중괄호)를 생략하여 표현. 추상클래스를 상속받은 후 해당 메소드를 오버라이딩함
abstract class Shape{
abstract void draw();
}
class Circle extends Shape{
void draw(){
System.out.println("원을 그립니다.");
}
}
class Rectangle extends Shape{
void draw(){
System.out.println("사각형을 그립니다.");
}
}
public class HelloWorld{
public static void main(String[] args){
Circle c1 = new Circle();
Rectangle r1 = new Rectangle();
c1.draw();
r1.draw();
}
}
자바에서는 여러 클래스를 다중 상속 불가능. 상속관계가 복잡해지면 알 수 없는 부작용 발생-> 인터페이스 활용하면 다중상속의 이점 활용 가능!
인터페이스)
특징 : 모든 메소드가 추상 메소드로 정의되어 있는 추상 클래스
상속을 받지 않기 때문에 다중 상속의 부정적 영향을 전혀 받지 않고 다중 상속의 장점 활용 가능, 상속은 기존 클래스의 속성을 확장하는 개념을 가지지만, 인페는 하나의 확장된 클래스로 기능을 제한하거나 가른 기능을 수행하도록 변경(다형성)
구현 : class대신 interface 키워드를 사용하여 구현하고, implements 키워드를 사용하여 상속, 확장된 클래스의 인스턴스를 상위 인터페이스 타입의 객체변수에 할당하여 기능을 변경하거나 제한
다중상속의 문제점 : 상위 클래스 A, B가 같은 클래스 C를 상속받는 경우와 같이 상속 관계가 복잡해지면 알 수 없는 부작용이 발생할 확률 상승.(다중상속-둘 이상의 상위 클래스를 상속 받는 것)
interface Coffee {
abstract void drink_coffee();
}
interface Cookie {
abstract void eat_cooke();
}
class Cafe implements Coffee, Cooke
{
public void drink_coffee() {
System.out.println("커피를 마신다.");
}
public void eat_cookie() {
System.out.println("쿠키를 먹는다.");
}
public void talk() {
System.out.println("대화를 한다.");
}
}
public class HelloWorld{
public static void main(){
Cafe k - new Cafe();
k.drink_coffee();
k.eat_cookie();
k.talk();
Coffee c = k;
c.drink_coffee();
Cooke x = k;
x.eat_cooke();
}
}
coffee, cookies 인터페이스 두개를 카페 클래스가 상속받아 오버라이딩하고 있음(implements), 그래서 카페 객체는 drink_coffee, eat_cookie, talk 3가지 메소드 사용 가능, 새로운 객체를 생성하면 3가지 메소드의 호출이 전부 가능!
그런데 3가지 기능이 가능한 카페 인스턴스를 일시적으로 drink_coffee만 가능하게 제한하고 싶으면
coffee c = k; 해당 객체를 커피 객체 변수에 할당하면 됨.(새롭게 커피 객체를 만들 필요 없이 카페 객체만으로도 커피 기능을 하는 객체 역할을 수행 할 수 있게 됨. 쿠키도 마찬가지)
하나의 확장된 객체로 모든 기능 또는 일부 기능만을 수행 할 수 있는 형태로 변형이 가능한 상태
=>다형성의 특징, 객체지향 기술의 궁극적인 목표
예외처리) 예외를 해결(처리)하는 코드를 구현
문법오류(Syntax Error) : 괄호를 잘 못 쓰거나, 함수명에 오타가 있는 등의 문법적인 부분 때문에 실행 전 발생하는 문제
예외 : 문법이나 표현식에 문제는 없지만 으도치 않은 작동 및 입력으로 문제가 발행, 예외를 식별할 영역을 별도로 지정하여 예외가 자주 발행하는 코드를 보완
try-catch : try블록 코드에서 예외가 발생하면 catch블록 코드 실행. try블록에서 발생한 예외로 인한 프로그램의 강제 종료 방지, 예외 발생이 빈번할 것으로 예상되는 영역을 try블록 지정
finally : 생략이 가능한 부분으로 예외 여부와 상관없이 항상 실행된
public class HelloWorld{
public static void main(String[] args){
//멤버 변수 영역
try{
// 예외 감지 영역
}
catch(){
// 예외 감지 시 실행 영역
}
finally{
// 무조건 실행되는 영역
}
}
}