객체 지향 언어

객체 지향 언어가 출현할 당시 가장 범용적으로 사용되는 언어는 절차 지향 언어였다. 객체 지향 언어는 절차 지향 언어의 단점을 보안고 다음 목적을 달성하기 위해 탄생했다.

- 소프트워어의 생산성 향상

 객체 지향 언어는 상속, 다형성, 객체, 캡슐화 등 소프트웨어의 재사용을 위한 여러장치를 내장하고 있다.

- 실세계에 대한 쉬운 모델링

 컴퓨터의 발전에 따라 실세계에서 발생하는 일을 프로그래밍해야 할 일이 더욱 많아지게 되었다. 객체의 속성과 행위를 묘사하고 객체 사이의 상호작용을 표현하는 방법으로 효과적인 프로그래밍을 할 수 있게 한다.

 C언어처럼 위에서부터 아래의 방향으로 절차대로 명령어를 실행하는 프로그램을 절차 지향 프로그램이라고 부르며 이런 언어를 절차 지향 언어라 한다. 이런 언어들은 흐름도를 설계하고 흐름도에 맞게 프로그래밍 함으로써 일련의 동작들이 순서에 맞게 실행되도록 작성한다.

 그러나 실제 세상은 각 물체 간의 관계, 상호 작용 등 훨씬 복잡하게 구성되어있다.이에 등장한 객체 지향 프로그램은 보다 실제 세상에 가깝게 모델링하여 물체를 객체로 표현한다.

객체지향 언어의 특성

-캡슐화

-상속

-다형성

-캡슐화(Encapsulation)

 캡슐화란 객체를 캡슐로 싸서 그 내부를 보호하고 볼 수 없게 하는것을 말한다. 자바에서 객체는 메소드(함수)와 필드 (데이터 변수)로 구성된다. 클래스라는 캡슐을 사용하여 객체를 표현하며 메소드(method)와 필드(field)를 클래스 내에 구현한다. 이렇게 함으로써 객체 외부에서는 객체 내의 숨겨놓은 메소드나 필드를 직접 접근할 수 없으며 메소드의 구현 내용도 알 수 없다. 몇몇 메소드와 필드는 객체 외부와의 인터페이스를 위해 노출된다.

 캡슐화의 목적은 객체 내 데이터에 대한 보안, 보호, 외부 접근 제한등을 위한것이다. 이때 외부에서 클래스 내부의 데이터 접근을 금지하는 것을 정보 은닉화라고 한다.

-상속(Inheritance)

 상속은 상위 개체의 속성이 하위 개체에 물려져서, 하위 개체가 상위 개체의 속성을 모두 가지고 있음을 의미한다. 예시로 동물은 생물의 속성을 갖고있고, 사람은 동물의 속성을 가지고 있다. 자바로 바꿔보면 동물은 생물의 부모 클래스이고 생물은 자식 클래스이다.

 자바에서 상속은 부모 클래스 즉 슈퍼 클래스(super class)를 자식 클래스 서브 클래스(sub class)가 상속받는것을 말한다. 상속은 이미 만들어진 클래스의 필드와 메소드를 물려받게 함으로써 자바 코드의 중복 작성을 방지하며, 코드의 재사용을 가능하게 한다.

-다형성(Polymorphism)

 다형성은 같은 이름의 메소드 호출에 대해 객체에 따라 다른 동작을 할 수 있도록 구현되는 것을 의미한다. 동물의 소리내기를 예로 든다면 개,고양이가 동물의 서브 클래스라 했을때 각각 개는 멍멍, 고양이는 야옹 하는 소리를 냈을 것이다. 이유는 개 고양이에 구현되어있는 소리내기는 각각 서로 다르기 때문이다. 이는 오버라이딩과 밀접한 관련이 있는데 오버라이딩은 다음에 오버로딩과 다시 다루겠다.

클래스와 객체 + 인스턴스

클래스는 객체들이 어떤 특성을 갖는다고 정의만 할 뿐 값을 가지지 않는다. 또한 객체의 행동에 대한 절차나 방법을 정의할 뿐 실제 행동을 하지않는다. 즉 클래스는 객체를 생성하기 위한 설계도 또는 틀이라 생각할 수 있다. 객체는 설계도 또는 틀로 찍어낸 실체라고 볼 수 있다. 이러한 이유로 객체를 클래스의 인스턴스 라고 부른다.

클래스 와 객체

클래스는 설계도 객체는 설계도로 구현한 모든 대상을 의미한다.

객체 와 인스턴스

클래스의 타입으로 선언되었을 때 객체라고 부르고, 그 객체가 메모리에 할당되어 실제 사용될 때 인스턴스라고 부른다.

객체는 현실 세계에 가깝고 인스턴스는 소프트웨어 세계에 가깝다.

엄격하게 객체와 인스턴스를 나누는것은 어렵다. 그래서 객체와 인스턴스 두 용어를 구별없이 사용한다.

클래스 구성

public class Person{ //클래스에 대한 접근 권한 - 키워드 - 클래스 이름
    public String name; //필드
    public int age;     //필드
    
    public Person(){ // 생성자(default)
    }
	public Person(String s){ // 생성자2
    	name = s
    }
    public String getName(){ //메소드
    	return name;
    }
}

위 코드가 기본적인 클래스의 구성이다. 이제 이 클래스로 객체를 생성해 보자.

객체 생성과 레퍼런스 변수

public static void main (String args[]){
   Person men;					// 객체에 대한 레퍼런스 변수 men선언
   men = new person("sejun");	// new 연산자 사용 person 객체 생성
   
   men.age=27;					//.을 이용해 객체 멤버 접근
   String s = men.getName();
}

위 코드는 객체를 생성하고 .을 이용해 객체 멤버에 접근하는 것을 보여준다.

Person men;  먼저 Person이라는 클래스의 레퍼런스 변수 men을 생성 했다. 객체를 생성할 때는 먼저 객체를 가르킬 레퍼런스 변수의 선언이 필요하다. men은 레퍼런스를 가지는 변수일 뿐 객체는 아니다.

자바에서는 반드시 new 연산자를 사용하여 객체를 생성해야 한다.

men = new person("sejun"); 이 문장의 실행 결과는

- Person 타입의 객체 메모리 공간 확보

- Person(String s){..} 생성자2가 실행되어 name 필드의 값을 "sejun"으로 설정

한것이다. 그럼 객체 men이 만들어진 것이다.

객체 멤버 접근

객체 멤버에 접근할 때는 점 . 연산자를 붙인다. men.age = 27; 은 men객체의 age필드에 27을 대입한 것이고, String s = men.getName(); 는 men객체의 getName() 메소드를 호출한 것이다.

조건 분기

조건 분기라는 단어는 다소 딱딱한 느낌이 든다. 쉽게 말해 C나 Java의 if문과 같다. 조건을 두고 그 조건과 참이면 해당문장을 실행하고 거짓이면 뛰어넘어 다음문장을 실행하는 것이다.

조건 분기 사용법

파이썬에서 '만약 A하면 B한다'를 표현하기 위해서 역시 if 를 사용한다.

if 조건문:
	실행문

조건문이 참이라면 실행문을 실행하고 거짓이면 실행하지 않고 넘어간다. 실행문 앞에 tap이나 스페이스 네 개를 넣어야 하는데 이것을 인덴트(indent) 라고한다. if문이나 반복문에 반드시 넣어야 하며 입력하지 않을 시 에러가 난다.

if문의 조건에 맞지 않을 때 다른 처리를 실행할려면 else라는 키워드를 사용한다.

if 조건문:
	조건이 ture일때 실행
else :
	조건이 false일때 실행

조건 분기에서는 elif 라는 키워드가 존재하는데, 이는 자바의 else- if와 같다. 즉 조건 분기를 여러차례 사용할 수 있다.

if 조건문1 :
	조건문1이 ture 일때 실행
elif 조건문2 :
	조건문2가 true 일때 실행
else :
	조건문 1,2 둘 다 false일때 실행

조건 분기 즉 if문을 사용시 주의할 점이 한가지 있다. 바로 조건을 쓰는 순서다. 조건을 쓰는 순서에 따라 처리 순서가 바뀔 뿐 아니라 처리 결과도 달라진다. 프로그램은 위에서 차례로 실행된다는 원칙을 따르기 때문인데 조건으로 분기하는 프로그램을 작성할때 조건들의 순서를 잘 고려해야 한다. 또한 중복 사용을 지양해야 하는데 이는 코드해석이 어렵기 때문이다. 이에 여러가지 조건을 쓸 수있다.

elif(A조건 or (B조건 and C조건)):
# 위와 같은 방법으로 조건을 여러개 쓸 수 있다.

반복문

프로그램이 가지는 장점 중 하나는 '많은 데이터를 처리할 수 있다'는 점이다. 파이썬에서는 for 나 while 이라는 키워드로 반복 처리를 할 수 있다.

for

for문의 서식은 다음과 같다.

for 변수 in range(반복하고 싶은 횟수) :
    반복시 동작 문장..
    반복시 동작 문장..
    

for 사용법

range() 괄호 안에 일반적으로는 문자가 들어가지만 문자열형 데이터를 넣는다면, 해당 문자열을 사용해 처리를 반복한다.

word = Hello
for str in word : #str : 변수 word : 반복횟수 
	print(str)
    
#출력문
H
e
l
l
o

문자열 데이터 뿐 만 아니라 리스트형 사전형이 들어갈 수 있다. 하지만 사전형 데이터를 사용할 때는 사전의 키가 들어가는것에 주의해야 한다.

while

반복 처리를 위한 키워드는 for이외에 while도 존재하는데 while은 일반적으로 무한 반복에서 사용한다. 서식은 다음과 같다.

while (조건식)
    반복할 처리..
    반복할 처리..

조건식이 true일 경우 반복하고 false가 될경우 반복을 종료한다. 조건식이 true일 경우에는 무한이 반복하는데 이때 반복을 종료시켜주는 키워드가 break이다. for문에서 동일하게 break를 사용할 수있다. 또한 반복문 도중에 처리를 넘기고 싶을 때는 continue 키워드를 사용한다.

'프로그래밍 공부 > Python' 카테고리의 다른 글

[Python] 5. 파이썬의 기본(5)  (0) 2020.01.29
[Python] 4. 파이썬의 기본(4)  (0) 2020.01.18
[Python] 3. 파이썬의 기본(3)  (0) 2020.01.14
[Python] 1. 파이썬의 기본(1)  (0) 2020.01.09

main()

main() 메소드는 자바에서 응용프로그램이 시작되는 메소드로서 특별한 의미를 가진다.

public static void main(String[] args){ 
}

원형은 이러하다. main() 메소드의 타입과 특징은

-자바 응용프로그램 실행은 main() 메소드부터 시작한다.

-main() 메소드는 public 속성이다. : 자바 가상 기계(JVM)에 의해 호출되어야 하므로 public 속성이다

-main() 메소드는 static 속성이다. : 클래스의 인스턴스(객체)가 생성되기 전에 호출되므로 static 속성이다.

-main() 메소드의 리턴 타입은 void 이다. : 아무 값도 리턴하지 않기 때문에

-main() 메소드는 인자는 무자열 배열(String [])이 전달된다. 

main() 메소드에 인자 전달

main() 메소드에서 받은 인자값은 args 배열을 통해 들어온다.

public class MainTest { 
     
     public static void main(String[] args) { 
           
           for(int i=0; i < args.length; i++) { 
                System.out.println("args[" + i + "] = " + args[i]);             
           }
           
     }
}

이렇게 되면 아무것도 넣지 않았기 때문에 출력값이 없지만 args 배열에 값을 넣어주면 문자형배열과 같이 출력된다.

예외

예외 : 프로그래밍 언에의 문법에 맞지 않게 프로그램을 작성하면 컴파일 오류(compile time error)가 발생한다. 그러나 프로그램 실행 중 계속 변하는 배열의 인덱스가 범위를 벗어나는 것은 컴파일 시점에서 걸러낼 수 없다. 이처럼 프로그램 실행 중 발생하는 런타임 오류(run time error)는 미리 걸러낼 수가 없어 자바에서는 예외(exception)를 사용해 처리한다. 대표적인 예외들이 아래 표에 있다.

예외 종류 예외 발생 경우
ArithmeticExecption 정수를 0으로 나눌 때 발생
NullPointerExecption null 래퍼런스를 참조할 때 발생
ClassCastExecption 변환할 수 없는 타입으로 객체를 변환할 때 발생
OutOfMemoryError 메모리가 부족한 경우 발생
ArrayIndexOutOfBoundsExecption 배열의 범위를 벗어난 접근 시 발생
IlleagalArgumentExecption 잘못된 인자 전달 시 발생
IOEExecption 입출력 동작 실패 또는 인터럽트 시 발생
NumberFormatExecption 문자열이 나타내는 숫자와 일치하이 않는 타입의 숫자로 변환 시 발생

예외 처리, try - catch - finally

예외 처리란 발생한 예외에 대해 개발자가 작성한 프로그램 내에서 대응하는 것을 말한다. 자바에서 예외 처리 시 try - catch - finally 문을 사용한다.

try{
	 예외가 발생할 가능성이 있는 실행문 (try 블록)
}
catch(처리할 예외 타입 선언){
	예외 처리문 (catch 블록)
}
finally{
	예외 발생 여부와 상관없이 무조건 실행되는 문장(finally 블록)
}//finally블록은 경우에 따라 생략이 가능하다.

try 안의 실행문에서 예외가 발생할 경우 catch문으로 이동하고 발생하지 않으면 finally 문아래 코드를 계속 실행한다.

배열이란?

배열(array)은 인덱스(index)와 인덱스에 대응하는 데이터들로 이루어진 자료구조

배열을 사용하는 큰 이유 중 하나는 반복문의 활용에 있다.

배열의 선언 및 생성

자바의 배열생성에는 두가지 단계가 필요하다.

(1) 배열에 대한 레퍼런스 변수 선언

(2) 배열 생성

배열 공간을 가르키기 위한 레퍼런스 변수 선언하는 단계(1)과 배열 공간을 할당하는 단계(2)로 구분된다.

(1) 배열에 대한 레퍼런스 변수 intArray 선언

int intArray []; // 순서대로 배열타입- 배열에 대한 레퍼런스 변수 - 배열선언

(2) 배열 생성

intArray = new int [5]; //배열에 대한 레퍼런스변수- 배열생성 - 타입 - 원소 개수

위 과정을 그림으로 나타내면

그림[4-1]

그림[4-1]과 같이 나타난다.

여기서 래퍼런스 변수는 intArray를 나타낸다. 레퍼런스 변수를 설명하기 위해선 인스턴스(instance)의 정의가 필요하다.

클래스를 사용하기 위해서는 반드시 메모리에 생성해 주어야 한다. 이렇게 메모리상에 생성된 클래스를 객체 혹은 인스턴스라고 부른다. 레퍼런스 변수메모리상에 생성된 인스턴스를 카리키는데 사용되는 변수이다. 위 그림에서 점으로 표현된 부분이 인스턴스이고 intArray가 해당 인스턴스를 가르키는 레퍼런스 변수인것이다. 모든 인스턴스는 레퍼런스 변수만을 통해서 사용이 가능하며, 일반적인 데이터를 넣어두는 변수가 아니고 인스턴스를 가르키는 값이다. 또한 레퍼런스 변수 . 을 이용해 인스턴스의 맴버 변수나 메소드를 사용할 수 있다.

배열참조

배열의 선언과 생성은 별개이다. 그러므로 한개의 배열을 다수의 레퍼런스가 참조할 수 있다.

 

그림[4-2]

그림[4-2]와 같이 각각 다른 레퍼런스 변수인 intArray와 myArray가 하나의 배열을 참조했다. 각각 배열의 인덱스를 참조할 수 있으며 변경시에 나중에 기록된것으로 바뀐다.

배열 원소 접근

배열의 원소에 대한 접근은 배열 레퍼런스 변수인덱스를 이용한다.

원소에 대한 인덱스는 0부터 시작한다.

int arr[] = new int[3];
arr[0] = 51;
arr[2] = 24;
int n = arr[2]; // 라고 했을때 n 의 출력 값은 24가 된다.

배열의 인덱스(index)는 정수만 가능하며 정수형 상수도 사용할 수 있다. 인덱스는 0부터 시작하며 마지막 원소의 인덱스는 (배열의 크기 -1)이 된다. 자바에서는 배열도 하나의 객체 처럼 다루어진다. 따라서 .length() 를 이용해 배열의 길이를 알고자 할때 사용한다.

int arr[];
arr = new int[31];

int arrSize = arr.length; // arrSize의 출력값은 31

for- each 문

for문을 변형해 배열이나 나열의 각 원소를 순차적으로 접근하기 편한 반복문이다. 반복 횟수는 지정한 배열의 인덱스 만큼이다.

String name[] = {"a","s","d","f","q"};
for(String s : name){
	System.out.printf(s);
}
//결과 값은 asdfq 총 for-each문은 5번 반복했다.

2차원 배열

2차원 배열은 1차원 배열을 겹쳐놓은 모양으로 선언은 다음과 같다

int arr1[][];
float arr2[][];

1차원 배열과 마찬가지로 레퍼런스 변수 선언 후 배열을 생성해야 한다.

arr1 = new int[4][2];
arr2 = new float[6][3];

메소드에서 배열 리턴

메소드에서 배열을 리턴할 수 있다. 이 경우 실제 배열에 대한 레퍼런스가 리턴된다. 메소드가 리턴하는 배열 타입과 배열의 차원은 리턴받는 배열 레퍼런스 변수의 타입과 배열의 차원에 일치해야 한다. 메소드 선언 시 배열의 크기는 매번 다를 수 있으므로 배열의 크기는 정하지 않는다.

int[] makeArr(){
    int temp[] = new int[4];
    return temp;
}

+ Recent posts