Ⅹ. 프로그래밍 언어 활용 - 객체지향문법 (C++, JAVA, 파이썬).
1. 클래스(Class)
- 겍체지향 프로그래밍(OOP; Object-Oriented Programming)에서 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀.
변수(Variable)와 메소드(Method)로 구성
- C++ 클래스 예제
#include <iostream> using namespace std; class A { //클래스명을 A로 지정 public: //외부에서 접근할 수 있도록 설정 void fn(){ //메소드명 fn 지정 cout << "메소드" << endl; //"메소드"라는 글자 출력 } } void main(){ A *a = new A(); // a라는 이름의 클래스 A 변수 설정 a->fn(); // a라는 변수의 fn 메소드 실행 }
- Java 클래스 예제
public class A { //클래스명을 A로 지정 public void fn(){ // 메소드명 fn, 외부접근 가능하도록 설정(public) System.out.println("메소드"); //"메소드"라는 글자 출력 } public static void main(String[] args){ A a = new A(); // a라는 이름의 클래스 A 변수 설정 a.fn(); // a라는 변수의 fn 메소드 실행 } }
- 파이썬 클래스 예제
class A: # 클래스명 A로 지정 def fn(); # 메소드명 fn 지정 print('메소드') # '메소드'라는 글자 출력 a = A; # a라는 변수에 A 클래스 저장 a.fn() # a 라는 변수의 fn 메소드 실행
// 출력 결과 메소드
- C++ 클래스내 사용자 정의함수 예제
#include <iostream> using namespace std; class A { //클래스명을 A로 지정 public: //외부에서 접근할 수 있도록 설정 int sum; int add(int a, int b){ //메소드명 add 지정 / 정수 a, b 입력 받음 sum = a+b; // sum 에 a+b 저장 return sum; //sum 반환 } }; void main(){ A *a = new A(); // a라는 이름의 클래스 A 변수 설정 cout << a->add(5, 7) << endl; // a라는 변수의 add 메소드에 5,7 값을 넣어 실행 & 출력 }
- Java 클래스내 사용자 정의함수 예제
public class A { //클래스명을 A로 지정 public int sum; //변수 sum 지정, 외부 접근가능 설정 public int add(int a, int b){ // 메소드명 add, 외부접근 가능하도록 설정(public), 정수 a, b 입력 받음 sum = a+b; // sum 에 a+b 저장 return sum; //sum 반환 } public static void main(String[] args){ A a = new A(); // a라는 이름의 클래스 A 변수 설정 System.out.println(a.sum(5, 7)); // a라는 변수의 add 메소드에 5,7 값을 넣어 실행 & 출력 } }
- 파이썬 클래스내 사용자 정의함수 예제
class A: # 클래스명 A로 지정 def add(a, b); # 메소드명 fn 지정, 정수 2개 입력 받음 sum = a+b # sum 에 a+b 지정 return sum # sum 리턴 a = A; # a라는 변수에 A 클래스 저장 print(a.add(5,7)) # a 라는 변수의 add 메소드 실행 & 출력
// 출력 결과 12
2. 상속(Inheritance)
상속이란 어떤 객체가 있을 때 그 객체의 변수와 메소드를 다른 객체가 물려받을 수 있는 기능.
- C++ 상속 예제
#include <iostream> using namespace std; class A{ //클래스 A 지정 public: //외부접근 설정 void fnA(){ //메소드명 fnA cout << "A 클래스" << endl; // "A 클래스" 글자 출력 } }; class B: public A{ //A클래스를 상속받은 클래스 B 지정 public: //외부접근 설정 void fnB(){ //메소드명 fnB cout << "B 클래스" << endl; // "B 클래스" 글자 출력 } } void main(){ B *b = new B(); //b라는 이름의 클래스 B에 대한 변수 설정 b->fnA(); //b라는 변수로 fnA 메소드 실행 b->fnB(); //b라는 변수로 fnB 메소드 실행 }
- Java 상속 예제
public class A{ //클래스 A 지정 public void fnA(){ //메소드명 fnA, 외부접근 설정 System.out.println("A 클래스"); // "A 클래스" 글자 출력 } } public class B extends A { //클래스 B 지정 public void fnB(){ //메소드명 fnB, 외부접근 설정 System.out.println("B 클래스"); // "B 클래스" 글자 출력 } } public class MainTest{ public static void main(String[] args){ B b = new B(); //b라는 이름의 클래스 B에 대한 변수 설정 b.fnA(); //b라는 변수로 fnA 메소드 실행 b.fnB(); //b라는 변수로 fnB 메소드 실행 } }
- 파이썬 상속 예제
class A: # 클래스명 A 지정 def fnA(): # 메소드명 fnA print('A 클래스') # 'A 클래스' 글자 출력 class B(A): # 클래스명 B는 A를 상속받음 def fnB(): # 메소드명 fnB print('B 클래스') # 'B 클래스' 글자 출력 b = B # b라는 이름의 클래스 B에 대한 변수 설정 b.fnA(); # b 라는 변수로 fnA 메소드 실행 b.fnB(); # b 라는 변수로 fnB 메소드 실행
// 출력 결과 A 클래스 B 클래스
3. 접근제어 지시자
- 종류
- private : 인스턴스 변수와 메소드는 선언된 클래스 내부에서 접근 가능.
- protected : 상속받은 클래스에 접근을 허용.
- public : 어디서든 접근 가능한 인스턴스 변수 및 메소드.
✱ 파이썬도 지원하지만 파이썬 private 는 변수앞 언더바( _ ) 두개, protected 는 변수앞 언더바 한개로 선언.- C++ 접근제어 지시자 예제
#include <iostream> using namespace std; class A { public: int r1; //r1은 클래스 내외부 접근 가능 protected: int r2; //r2는 클래스 내부 및 상속받은 클래스에서만 접근 가능 private: int r3; //r3는 클래스 내부만 접근 가능 public: void add(int a, int b){ r1 = a+b; //public 으로 된 r1 변수 접근 가능 cout << r1 << endl; } void sub(int a, int b){ r2 = a-b; //protected 로 된 r2 변수 접근 가능 cout << r2 << endl; } void mul(int a, int b){ r3 = a*b; //private 로 된 r3 변수 접근 가능 cout << r3 << endl; } }; class B: public A{ //B클래스는 A클래스 상속 pubilc: void div(int a, int b){ r1 = a/b; //public 으로 된 r1 변수 접근 가능 count << r1 << endl; } void rem(int a, int b){ r2 = a%b; //상속 받았으므로 protected 로 된 r2 변수 접근 가능 cout << r2 << endl; } }; void main(){ B *b = new B(); //b 라는 이름이 클래스 B에 대한 변수 설정 b->add(7,4); //add는 public 함수이므로 접근 가능 b->sub(7,4); //sub는 public 함수이므로 접근 가능 b->mul(7,4); //mul는 public 함수이므로 접근 가능 b->div(7,4); //div는 public 함수이므로 접근 가능 b->rem(7,4); //rem는 public 함수이므로 접근 가능 }
- Java 접근제어 지시자 예제
public class A{ public int r1; //r1은 클래스 내외부 접근 가능 protected int r2; //r2는 클래스 내부 및 상속받은 클래스에서 접근 가능 private int r3; //r3는 클래스 내부만 접근 가능 public void add(int a, int b){ r1 = a+b; //public 인 r1 변수에 접근 가능 System.out.println(r1); } public void sub(int a, int b){ r2 = a-b; //protected 인 r2 변수에 접근 가능 System.out.println(r2); } public void mul(int a, int b){ r3 = a*b; //private 로 되어있는 r3 변수 접근 가능 System.out.println(r3); } } public class B extends A { // B클래스는 A 클래스 상속 void div (int a, int b){ r1 = a/b; //A클래스에 public인 r1변수 접근 가능 System.out.println(r1); } void rem (int a, int b){ r2 = a%b; //A클래스에 protected인 r2변수 접근 가능(상속받았으니까) System.out.println(r2); } } public class MainTest { public static void main(String[] args){ B b = new B(); //b 라는 이름의 클래스 B에 대한 변수 설정 b.add(7,4); //add는 public 함수이므로 접근 가능 b.sub(7,4); //sub는 public 함수이므로 접근 가능 b.mul(7,4); //mul은 public 함수이므로 접근 가능 b.div(7,4); //div는 public 함수이므로 접근 가능 b.rem(7,4); //rem은 public 함수이므로 접근 가능 } }
// 출력 결과 11 3 28 1 3
4. 오버로딩(Overloading)
- 동일 이름의 메소드를 여러개 정의할 수 있는 특성 - C++, JAVA
- 오버로딩 특징
- 메소드 이름이 같아야 한다.
- 매개변수 개수가 달라야 한다.
- 매개변수 개수가 같을 경우 데이터 타입이 달라야 한다.
- 반환형은 같거나 달라도 된다.
- 파이썬은 메소드 오버로딩을 지원하지 않는다.
- C++ 오버로딩(Overloading) 예제
#include <iostream> using namespace std; class A { // A 클래스 선언 pubilc: void fund(){ // 매개변수가 없고 반환 값도 없는 func() 메소드 count << "매개변수 없음" << endl; } void func(int i){ //하나의 정수형 매개변수를 갖고 반환값이 없는 func() 메소드 count << i << endl; } void func(double d){ //하나의 실수형 매개변수를 갖고 반환값이 없는 func() 메소드 count << d << endl; } int func(int a, int b){ //두개의 매개변수를 갖고 정수형 반환값이 있는 func() 메소드 return a+b; } }; void main(){ A *a = new A(); //a 라는 이름이 클래스 A에 대한 변수 설정 a->func(); //매개변수 없는 func() 메소드 호출 a->func(7); //하나의 정수형 매개변수를 갖는 func()메소드 호출 a->func(10.0); //하나의 실수형 매개변수를 갖는 func() 메소드 호출 cout << a->func(2,3) << endl; //두개의 매개변수를 갖고 반환값을 갖는 func() 메소드 호출 }
- Java 오버로딩(Overloading) 예제
public class A{ //A클래스 선언 public void func(){ // 매개변수가 없고 반환 값도 없는 func() 메소드 System.out.println("매개변수 없음"); } public void func(int i){ //하나의 정수형 매개변수를 갖고 반환값이 없는 func() 메소드 System.out.println(i); } public void func(double d){ //하나의 실수형 매개변수를 갖고 반환값이 없는 func() 메소드 System.out.println(d); } public int func(int a, int b){ //두개의 매개변수를 갖고 정수형 반환값이 있는 func() 메소드 return a+b; } } public class MainTest { public static void main(String[] args){ A a = new A(); // 클래스 A의 객체 a 생성 a.func(); //매개변수 없는 func() 메소드 호출 a.func(7); //하나의 정수형 매개변수를 갖는 func()메소드 호출 a.func(10.0); //하나의 실수형 매개변수를 갖는 func() 메소드 호출 System.out.println(a.func(2,3)); //두개의 매개변수를 갖고 반환값을 갖는 func() 메소드 호출 } }
// 출력 결과 매개변수 없음 7 10.0 5
5. 오버라이딩(Overriding)
- 오버라이딩이란 하위 클래스에서 상위클래스 메소드를 재정의 할 수 있는 특성이다.
- 오버라이딩 특징
- 오버라이드 하고자 하는 메소드가 상위 클래스에 존재하여야 한다.
- 메소드 이름은 같아야 한다.
- 메소드 매개변수 개수, 데이터 타입이 같아야 한다.
- 메소드 반환형이 같아야 한다.
- C++ 오버라이딩(Overriding) 예제
#include <iostream> using namespace std; class A { // 부모클래스 A 선언 public: virtual void info(){ //메소드 오버라이드를 위한 info 메소드 선언부 앞에 virtual 키워드를 붙임 cout << "Parent" << endl; //"Parent" 글씨 출력 } }; class B: public A { //A클래스를 상속받은 자식클래스 B 선언 public: //메소드 오버라이드를 위한 메소드 선언부앞에 virtual 붙임, 뒤에는 override 키워드 붙임. virtual void info() override{ A::info(); //부모클래스 info 메소드 호출 cout << "Child" << endl; //"Child" 글씨 출력 } }; void main(){ A *a = new B(); // 부모 클래스 변수 타입으로 선언하고 자식클래스로 생성(동적바인딩) a->info(); // a라는 변수로 info 메소드 호출 }
- Java 오버라이딩(Overriding) 예제
public class A{ //부모클래스 A선언 public void info(){ //메소드 오버라이드를 위한 info메소드 선언 System.out.println("Parent"); //"Parent" 글자 출력 } } public class B extends A{ //부모클래스 A를 상속받은 자식클래스 B 선언 public void info(){ super.info(); //info 메소드 선언 및 오버라이드함 System.out.print("Child"); //"Child" 글자 출력 } } public class MainTest{ public static void main(String[] args){ A a = new B(); // 부모클래스 변수타입으로 선언하고 자식클래스로 생성(동적바인딩) a.info(); //a 라는 변수로 info 메소드 호출 } }
// 출력 결과 Parent Child
6. 인터페이스(Interface)
- 자바의 다형성을 극대화 하여 개발코드 수정을 줄이고 프로그램 유지보수성을 높이기 위한 문법.
- 인터페이스는 일종의 추상클래스 이다.
- 오직 추상메소드와 상수만을 멤버로 가질 수 있으며, 그외 다른 어떠한 요소도 허용하지 않는다.
인터페이스는 구현된것이 아무것도 없고 밑그림만 있는 “기본설계도”라 할 수 있다.
- C++ 인터페이스 예제
#include <iostream> #define interface struct //구조체를 이용하여 인터페이스 정의 using namespace std; interface A { // 인터페이스 A 선언 virtual void callTest()=0; //추상메소드를 통해 callTest를 정의 }; class B: public A{ //인터페이스 A를 상속받은 클래스 B선언 public: virtual void callTest(){ //callTest 메소드를 통해 "Interface Test"를 출력 cout << "Interface Test" << endl; } }; void main(){ A *b = new B(); //A객체 타입의 B 객체 생성 b->callTest(); //callTest 메소드를 호출 }
- Java 인터페이스 예제
interface A{ // A 인터페이스 선언 void callTest(); //callTest 메소드 선언 } class B implements A{ //A를 구현하는 B클래스 선언 public void callTest(){ System.out.println("Interface Test"); // "Interface Test" 글자 출력 } } class MainTest{ public static void main(String[] args){ A b = new B(); //A객체 타입의 B객체 생성 b.callTest(); //callTest 메소드 호출 } }
// 출력 결과 Interface Test
7. 추상 클래스(Abstract Class)
- 추상클래스란 미구현 추상 메소드를 한개 이상 가지며, 자식 클래스에서 해당 추상메소드를 반드시 구현하도록 강제하는 문법이다.
- 상속받은 클래스는 추상메소드를 구현하지 않아도, import 할 때까지 에러는 발생하지 않으나 객체를 생성할 시 에러가 발생한다.
- 추상 클래스의 장점
- 중복코드 제거 : 상속을 통해 중복코드를 줄일 수 있음.
- 그룹화 : 자식 클래스를 그룹화가 가능.
- 비 실존 객체 생성 차단 : 비 실존 객체의 직접 생성을 차단하여 실수를 사전 방지.
- C++ 추상클래스 예제
#include <iostream> using namespace std; class A { // 추상클래스 A 선언 public: virtual void callTest()=0; }; class B: public A{ //A를 상속받은 클래스 B 선언 public: virtual void callTest(){ cout << "B 클래스" << endl; // callTest() 메소드를 통해 "B 클래스" 글자 출력 } }; class C: public A{ //A를 상속받은 클래스 C 선언 public: virtual void callTest(){ cout << "C 클래스" << endl; // callTest() 메소드를 통해 "C 클래스" 글자 출력 } }; void main(){ A *b = new B(); //A 객체 변수a 에 B객체 생성 A *c = new C(); //A 객체 변수c 에 c객체 생성 b->callTest(); //callTest 메소드 호출 c->callTEst(); //callTest 메소드 호출 }
- Java 추상클래스 예제
abstract class A { //추상클래스 A 선언 abstract void callTest(); //추상메소드 callTest() 선언 } class B extends A { //A를 상속받은 B void callTest(){ System.out.println("B 클래스"); //callTest 메소드를 통해 "B 클래스" 글자 출력 } } class C extends A { //A를 상속받은 C void callTest(){ System.out.println("C 클래스"); //callTest 메소드를 통해 "C 클래스" 글자 출력 } } class MainTest{ public static void main (String[] args){ A b = new B(); //B객체 생성 A c = new C(); //C객체 생성 b.callTest(); //callTest 메소드 호출 c.callTest(); //callTest 메소드 호출 } }
- 파이썬 추상클래스 예제
class A: # 추상클래스 A 선언 def callTest(self): # 추상메소드 callTest() 선언 pass # 메소드 냉ㅇ을 채우지 않음. class B(A): # A를 상속받은 B def callTest(self): print('B 클래스') #'B 클래스' 글자 출력 class C(A): # A를 상속받은 C def callTest(self): print('C 클래스') # 'C 클래스' 글자 출력 b = B() #b라는 변수명으로 B 객체 생성 c = C() #c라는 변수명으로 C 객체 생성 b.callTest() #b변수로 callTest 호출 c.callTest() #c변수로 callTest 호출
// 출력 결과 B 클래스 C 클래스
8. 인터페이스와 추상 클래스의 비교
8.1. 인터페이스와 추상 클래스 공통점
- 추상클래스와 인터페이스는 선언만 있고 구현 내용이 없는 클래스이다.
- 자기 자신이 new를 이용해 객체를 생성할 수 없으며, 추상클래스를 extends 받거나 interface를 implements한 자식만이 객체를 생성할 수 있다. 상속받은 자식이 구현을 반드시 하도록 해야 할 때 사용한다.
- JAVA에서는 타입이 지정되었기 때문에 선언된 타입과 자식의 타입이 같아야만 한다.
8.2. 인터페이스와 추상클래스의 차이점
- 상속을 받음에도 불구하고 클래스에선 상속(Inheritance)이라고 쓰지만, 인터페이스는 구현(Implements)이라고 쓴다.
- 추상클래스를 상속받는 클래스는 반드시 추상메소드를 구현해야 한다. 필수적으로 구현해야 할 메소드가 있을때 추상 클래스를 쓰게 된다.
- 인터페이스를 상속받는 클래스에서는 반드시 인터페이스에 있는 메소드를 다 구현해야 한다.
- 정보처리기사 필기 합격 후 실기대비 정리 및 책없이 간단히 보기위해 작성하였습니다.
- 2020년 수제비 정보처리기사 책 기반으로 정리 하였습니다.
- 저작권 관련 문제가 있다면 hojunbbaek@gmail.com 으로 메일 주시면 바로 삭제 조치 하도록 하겠습니다.
[정보처리기사 실기] Ⅹ. 프로그래밍 언어 활용- 객체지향문법(C++, JAVA, 파이썬). (feat.수제비)