Search

반응형

'Software'에 해당되는 글 190건

  1. 2020.05.05 [자바]추상클래스 vs. 인터페이스 사용방법. Abstract Class vs. Interface
  2. 2020.05.03 [자바]StringBuffer vs. String 메모리 관리하기.
반응형

안녕하세요. 프로그래머 티보이입니다.

이번에 할 이야기는 바로 추상클래스와 인터페이스입니다. (Abstract Class, Interface)

자바를 배우고 사용하시는 분들에게는 아주 중요한 개념이므로 같이 정리해보겠습니다.

 

 

먼저 개념 정리부터 하겠습니다. (오늘은 코딩 없이 가 봅시다!!)

 

#추상클래스 (Abstract Class)

abstract [class_name] {
           abstract [return_type][method_name]();
}

 

추상클래스는 제어자 abstract를 사용해야 한다.

객체지향의 다형성을 위해 만드는 추상클래스는 다양한 클래스들의 공통된 부분을 묶어서 상속받을 수 있게 한다.

추상클래스는 제어자인 abstract로 구현한 추상메소드를 반드시 하나는 가지고 있어야 한다.

추상클래스에서만 추상메소드를 사용할 수 있고 추상메소드 선언 끝에 세미콜론(;)을 반드시 붙인다.

추상클래스는 자체로 객체를 생성(인스턴스화)할 수 없다.

extends(확장) 키워드를 사용해서 추상클래스를 상속 받을 수 있다. (상속은 단 1개만 가능)

추상클래스를 상속받으면 추상메소드는 반드시 재구현(override, 오버라이딩)해야 한다.

추상클래스는 다른 일반 클래스처럼 메소드와 변수를 선언 및 구현할 수 있고 자식클래스가 그대로 상속받아 사용할 수 있다.

 

#인터페이스 (Interface)

interface [interface_name] {

          Public static final [constant_name] = value;

           Abstract [return_type][method_name]();

}

 

인터페이스는 interface 키워드로 선언한다.

클래스는 implements(구현) 키워드로 여러 개의 인터페이스를 구현할 수 있고 물론 extends로 클래스를 상속 받는 것도 동시에 가능하다.

인터페이스를 implements하면 선언된 메소드를 모두 구현해줘야 한다.

메소드는 선언만 가능하고 구현할 수 없다. (추상메소드지만 abstract는 생략가능)

상수를 선언할 수 있다. (static final)

변수도 선언할 수 있다.

인터페이스끼리 extends를 사용해 상속이 가능한데 하나만 가능한 클래스와 달리 여러 개 가능하다.

 

여기까지는 보통 자바책을 보면 나와있는 내용입니다.

 

추상클래스와 인터페이스는 비슷한 듯 다른점이 있는데요.

추상클래스는 1개만 상속 가능, 인터페이스는 여러 개 구현 가능하고 인터페이스끼리는 여러 개 상속 가능.

추상클래스는 구현한 메소드가 존재하지만 인터페이스는 선언메소드만 가능.

 

이렇게 구분하는 것도 각각의 특징을 보면 알 수 있답니다.

 

그런데 가장 중요한 것은,

항상 교재를 이용해서 이론을 공부하다 보면 대부분 정의를 먼저 내립니다.

그리고 작성법을 알려주며 간단하게 비교도 해줍니다.

그렇게 이해하고 정리가 되긴 했는데

어떤 경우에 어떻게 사용하는지 설명하는 책은 아직 못찾았습니다.

혹시 여러분들도 그런 갈증을 해소하기 위해 책이 아닌 웹사이트를 검색하다 오신거 맞으시죠?

그런 부분을 설명해주는 것이 블로그의 묘미 아닐까 싶네요.

 

실전에서 어떻게 하는지는 설계자나 프로그래머의 몫입니다.

제 기준으로 간단히 설명해 볼께요.

 

반지의 제왕과 비슷한 게임 프로그램을 만든다고 가정하겠습니다.

유닛들을 만들어야 합니다.

유닛들은 객체로 구성할 수 있겠네요.

그렇다면 객체를 구성할 클래스를 설계해야 합니다.

모든 객체는 생명체입니다.

모든 생명체는 눈도 있고 심장도 뛰고(아직 살아있는지 죽었는지 판단시) 팔, 다리, 날개 및 꼬리 등이 있고 개수는 다를 수 있겠지요.

모든 생명체는 걷기, 뛰기, 공격, 방어, 날기 및 공격 포인트, 방어 포인트도 있을 것이고 무기관련 장착, 사용, 업그레이드 같은 기능이 있을 겁니다.

인간 객체, 오크 객체, 동물 객체, 요정 객체 등 다양한 객체들도 있을 거구요.

이렇게 간단하게 구상을 하고 설계를 한다고 했을 경우입니다.

모두 생명체이기에 추상클래스를 하나 만듭니다.

생명체는 기본적으로 눈, 심장, , 다리, 날개 등 기본값(변수) 및 설정하는 메소드(set)를 추상메소드로 선언해서 상속 받는 각 객체 클래스들에서 구현하게 합니다. 그리고 각 객체들의 현재 상태를 확인할 수 있는 메소드를 구현합니다.

이렇게 추상클래스는 객체들을 생성할 클래스의 공통점을 추출해서 기본 설정을 한군데 모아서 상속받아 사용할 수 있게 구성했습니다.

 

이제 인간, 오크, 동물, 요청 클래스는 생명체 추상 클래스를 상속 받아서 기본 값을 설정하는 메소드를 구현하고 현재 상태를 확인하는 메소드를 재정의 할 수도 있게 되었습니다.

 

다음으로 생각할 부분은 각 객체들은 걷기, 날기, 뛰기, 수영하기 등의 액션을 할 수 있고,

공격, 방어 등의 기능도 만들어야 합니다.

필수적인 이 기능들은 모든 객체들이 구현해야 하기 때문에 인터페이스로 구성합니다.

공격 명령을 내렸을 때 객체가 공격하기를 원한다면 그 공격 명령을 받고 실행할 부분이 필요하겠지요? 그런 부분들을 인터페이스로 구성하면 되겠네요.

그렇다면 인터페이스도 좀 더 분류해서 만들면 좋습니다.

우선 개념만 이해는 부분이니 두개의 인터페이스만 구성해봅니다.

기본적인 활동을 하는 걷기, 뛰기, 날기, 수영하기 등의 메소드를 선언한 인터페이스 하나와

능력을 표현하는 공격, 방어, 업그레이드, 수송 등의 메소드를 선언한 인터페이스로 구성합니다.

 

이제 인간, 오크, 동물, 요정등을 생성할 수 있는 클래스를 만들 것이고,

이 객체들이 생명체이기에 기본적으로 구성할 부분을 추출해서 공통(추상)화 한 추상클래스를 만들어 상속받게 하며,

각 객체들의 움직임과 능력에 대한 표현을 선언한 각각 인터페이스를 구현하면 됩니다.

 

이렇게 추상클래스와 인터페이스 사용에 대해 혼란스러워 하지 말고,

각 특징을 잘 이해하고 위 예시처럼 재량껏 사용하면 될 듯합니다. 

실전에서는 더 자세하고 많은 클래스와 인터페이스가 존재하겠지요?

추상클래스와 인터페이스를 어떻게 사용할 것인지 또한 설계자와 프로그래머의 노하우가 필요하지 않을까 싶네요.

즐코딩하세요~

반응형
반응형

즐코딩 하고 계시나요?

코딩은 즐겁게 해야 시간도 잘갑니다. ㅎㅎ

이번 포스팅은 StringBufferString 타입에 대해 설명해봅니다.

예전에 자바 초보시절 겪었던 일입니다.

그때는 나름 한다고 생각했지만 사실 초보였지요.

 델파이(Delphi)나 비주얼베이직(VB) 개발자에서 자바로 건너온 지 그리 오래 되지 않았었고,

깊이 있게 자바를 생각하지 않고 사용하던 시절이었네요..ㅋㅋ

여튼 자동으로 HTML을 만드는 프로그램을 만들던 중 문자 데이터를 결합해야 하는데..

그냥 String으로 선언하고 그 변수에 += 로 계속 이어 나갔습니다.

어떤 결과가 나왔을지 여러분은 아시겠죠?

메모리 오버나고 속도 개 느려지고 ㅋㅋ ..

왜 그럴까? 이게 안되는게 말이 되나? 그럼 어쩌란말인가?

라면서 고민하던 중 큰 실수를 했다는 것을 알았답니다.

String 변수에 +나 += 로 계속 문자열을 붙이면 선언한 변수 하나에 붙여지는게 아니라,

새로 메모리를 차지하면서 중복되는 정보가 계속 쌓이는 구조였습니다.

그래서 여러개의 문자열을 대량으로 이어 붙이는 경우 (네트워크 전송 데이터 등)

String으로 사용하면 안되는거에요.

하나의 변수에 대량의 문자열들을 이어 붙이기 위해서는 StringBuffer 클래스의 객체를 이용하면 됩니다.

그러면 단 하나의 객체로 데이터가 쭉 이어져서 붙여집니다.

예를 통해서 StringBuffer 클래스로 객체도 생성하고 해당 메소드의 사용법도 살펴보겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
StringBuffer sb1 = new StringBuffer();
 
sb1.append("abcde");
System.out.println(sb1.toString()); 
 
sb1.delete(24);
System.out.println(sb1.toString()); 
 
sb1.deleteCharAt(0);
System.out.println(sb1.toString()); 
 
sb1.insert(0"a");
sb1.insert(2"cd");
System.out.println(sb1.toString()); 
 
System.out.println(sb1.indexOf("c"));
 
System.out.println(sb1.indexOf("f"));
        
System.out.println(sb1.lastIndexOf("d"));
 
sb1.replace(34"234");        
 
System.out.println(sb1.toString());
 
System.out.println(sb1.substring(2));
 
System.out.println(sb1.length());
 
 
StringBuffer sb2 = new StringBuffer();
 
sb2.append("abcdefabcdef");
 
System.out.println(sb2.indexOf("c"));
System.out.println(sb2.indexOf("c"5));
 
System.out.println(sb2.lastIndexOf("c"));
System.out.println(sb2.lastIndexOf("c"8));
System.out.println(sb2.lastIndexOf("c"7));
cs

 

코딩에 필요하면 복사해서 사용하면 됩니다. ^^

우선 StringBuffer 객체를 생성합니다.

 

StringBuffer sb1 = new StringBuffer();

이렇게요.

sb1에 원하는 문자열들을 집어 넣습니다.

 

sb1.append("abcde");

append 메서드는 제일 마지막 부분에 입력한 문자열을 붙입니다.

결과를 확인할 때는 sb1이 객체이므로 toString() 메서드를 이용합니다.

 

System.out.println(sb1.toString()); 

결과는 "abcde"가 나옵니다.

이 상태에서 sb1.append("fgh");를 하면 제일 뒤에 "fgh"를 붙여서 "abcdefgh"가 됩니다.

 

sb1.delete(24);

delete메소드는 문자열을 삭제하는 기능입니다.

파라메터는 문자열 시작 인덱스에서 삭제하고 싶은 문자열 다음 인덱스로 설정합니다.

(2, 4)로 2에서 시작하니 "c"부터 삭제하면서 4 앞까지 삭제하니 "d"까지 삭제하겠네요.

결과는 "abe"가 나옵니다. 주의할 점은 두번째 파라메터인 4까지가 아니라 4 앞까지입니다.

 

sb1.deleteCharAt(0);

문자 한개의 위치를 지정해서 삭제합니다. 위치 인덱스가 0이므로 "a"만 삭제 됩니다.

 

sb1.insert(0"a");

sb1.insert(2"cd");

insert 메서드는 원하는 위치에 문자 또는 문자열을 추가할 수 있습니다.

두번째 (2, "cd")는 2번 인덱스와 3번 인덱스 사이에 "cd"를 넣는거에요. 3번이 뒤로 밀려납니다.

 

sb1.indexOf("c");

sb1에서 c의 위치 인덱스를 반환합니다. 

결과는 "2"가 나옵니다.

 

sb1.indexOf("f");

"f"를 찾지만 문자열에 없습니다. 

결과가 없는 경우는 "-1"을 리턴합니다.

 

System.out.println(sb1.lastIndexOf("d"));

lastIndexOf 메서드는 "d"를 찾을 때 처음부터 찾는게 아니라 문자열 제일 뒤에서부터 찾습니다.

그리고 위치가 확인되면 위치 인덱스는 앞에서부터 계산해서 보여줍니다.

결과는 "3"이 나옵니다. 

sb1.replace(34"234");

replace 메서드는 지정한 위치에 원하는 문자열을 대체하는 겁니다.

insert는 기존 문자열 사이에 집어 넣지만 replace는 지정한 위치의 문자 대신해서 넣는데 지정한 길이보다 길어도 변환이 됩니다.

결과는 "abc234e"가 나옵니다.

 

sb1.substring(2);

원하는 인덱스 위치를 넣으면 그 위치부터 뒤로 끝까지 문자들을 반환합니다.

결과는 "c234e"가 나옵니다.

 

sb1.length();

문자열 전체 길이를 반환합니다.

결과는 "7"이 나옵니다.

 

sb2.indexOf("c"5);

이 경우는 문자 "c"를 5번째 인덱스부터 찾아서 반환하라는 의미입니다.

결과는 두번째 "c"의 위치인 "8"이 반환됩니다. 첫번째 "c"의 인덱스는 2이지만 5부터 찾으라고 했기 때문입니다.

 

sb2.lastIndexOf("c"8);

이 메서드는 "c"문자를 8번째 문자열부터 시작해서 찾습니다. 두번째 "c"의 위치가 8이기에 두번째 위치인 "8"이 나옵니다.

 

sb2.lastIndexOf("c", 7);

이렇게 7로 바꾸게 되면 8번째 "c"가 포함되지 않기에 2번 인덱스의 "c"가 검색됩니다.

그래서 결과는 "2"가 나옵니다.

네트워크 전송 데이터를 결합하거나 또는 긴 문자열을 다룰 때는 StringBuffer를 사용해보세요.

즐코딩하세요~

 

반응형