본문 바로가기

프로그래밍 언어 정리/기초 다지기

[기초 다지기 - 2] 클래스

이름, 나이, 성적을 담을 수 있는 클래스를 만들고, 여러 기능(메소드)을 추가하여 코드를 작성하겠습니다.

 

구현할 메소드는 아래와 같습니다.

 

  • 이름, 나이, 성적을 인자로 받아 객체를 만드는 생성자
  • 현재 객체와 인자로 받은 객체를 비교하여 누구의 성적이 더 높은지 반환하는 문자열 타입 메소드
  • 숫자 하나를 인자로 받아 해당 학생의 점수가 숫자보다 높은지 반환하는 boolean 타입 메소드
  • 정렬 시 학생들의 번호가 내림차순으로 정렬(점수가 같다면 번호를 오름차순으로 정렬) 될 수 있도록 하는 우선순위 메소드. 

객체 지향 언어를 사용하나, 편의를 위해 정보를 은닉하지 않았습니다. 문제 풀이 환경이 아니라면 꼭 은닉화를 하는 것을 권장합니다.

 


[Java]

 

import java.io.*;
import java.util.*;

// Comparable로부터 상속받아 compareTo를 사용
class Student implements Comparable<Student> {

    // 필드 (변수들)
    String name;
    int num, score;

    // 생성자
    public Student(String name, int num, int score) {
        this.name = name;
        this.num = num;
        this.score = score;
    }
    
    // 객체를 받아 현재의 학생과 비교하여 누구의 성적이 더 높은지 반환하는 문자열 타입 메소드
    public String greaterStudent(Student st) {
        String temp;

        if (this.score > st.score) temp = this.name;
        else if (this.score < st.score) temp = st.name;
        else temp = "두 학생의 성적이 같습니다.";
        
        return temp;
    }

    // 정수 N를 받아 현재 학생의 성적이 N보다 높은지를 반환하는 boolean 타입 메소드
    public boolean isHigher(int N) {
        if (this.score > N) return true;
        else return false;
    }

    // 객체끼리의 우선순위를 정하기 위해 Comparable에서 상속 받아 온 compareTo 메소드 
    @Override
    public int compareTo(Student st) {
        if (this.score == st.score) return this.num - st.num;
        return st.score - this.score;
    }
}

public class Main {
	public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // 생성자로 객체 생성
        Student st1 = new Student("박형기", 4, 83);
        Student st2 = new Student("이건우", 2, 83);
        Student st3 = new Student("박세인", 3, 18);
        Student st4 = new Student("김현진", 5, 100);
        Student st5 = new Student("강지훈", 1, 33);
        
        // 문자열 타입 메소드 작동 확인
        System.out.println(st1.greaterStudent(st2));
        System.out.println(st2.greaterStudent(st3));
        System.out.println(st4.greaterStudent(st5));

        System.out.println();
        
        // boolean 타입 메소드 작동 확인
        System.out.println(st1.isHigher(83));
        System.out.println(st3.isHigher(50));
        System.out.println(st4.isHigher(50));

        System.out.println();

        // compareTo 메소드 작동 확인
        Student[] book = new Student[5];
        book[0] = st1; book[1] = st2; book[2] = st3; book[3] = st4; book[4] = st5;

        Arrays.sort(book);

        for (Student st : book) {
            System.out.println(st.num + " " + st.name + " " + st.score);
        }
    }
}

 

간단한 설명은 주석에 달았습니다.

 

추가로 compareTo에 대해서는 부연 설명을 하겠습니다.

 

  • 해당 클래스가 Comparable을 상속 받아야 사용이 가능하고, Comparable에 구현된 메소드를 오버라이딩 하는 것이기 때문에 @Overriding을 달아줘야 합니다. 
  • compareTo는 정수 타입입니다. 음수를 반환하면 현재 값이 비교군보다 앞에 있어야 하고,  양수를 반환하면 그 반대입니다. 0을 반환하면 어떤 정렬을 사용하느냐에 따라 결과가 달라집니다. 0을 반환할 일이 없게 처리를 하는 것이 좋습니다.
  • compareTo를 사용하지 않아도 단순 비교는 가능합니다. greaterStudent 메소드를 만들어서 사용한 것처럼 하면 됩니다. 그러나 우선순위 큐나 자바 내부에서 구현한 정렬은 compareTo를 기반(Comparator도 사용)으로 정렬하기 때문에 위 코드처럼 Arrays.sort를 쓰는 경우에는 compareTo를 구현해야 합니다.

[C++]

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Student {
public:
    // 필드 (변수들)
    string name;
    int num, score;

    // 생성자
    Student(string name, int num, int score) {
        this->name = name;
        this->num = num;
        this->score = score;
    }

    // 객체를 받아 현재의 학생과 비교하여 누구의 성적이 더 높은지 반환하는 문자열 타입 메소드
    string greaterStudent(Student st) {
        string temp;

        if (this->score > st.score) temp = this->name;
        else if (this->score < st.score) temp = st.name;
        else temp = "두 학생의 성적이 같습니다.";

        return temp;
    }

    // 정수 N을 받아 현재 학생의 성적이 N보다 높은지를 반환하는 bool 타입 메소드
    bool isHigher(int N) {
        if (this->score > N) return true;
        else return false;
    }

    // 객체끼리의 우선순위를 정하기 위해 <연산자 오버로딩
    int operator<(const Student& st) const {
    	if (this->score == st.score) return this->num << st.num;
        return this->score > st.score;
    }

};

int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    // 생성자로 객체 생성
    Student st1 = Student("박형기", 4, 83);
    Student st2 = Student("이건우", 2, 83);
    Student st3 = Student("박세인", 3, 18);
    Student st4 = Student("김현진", 5, 100);
    Student st5 = Student("강지훈", 1, 33);

    // 문자열 타입 메소드 작동 확인
    cout << st1.greaterStudent(st2) << '\n';
    cout << st2.greaterStudent(st3) << '\n';
    cout << st4.greaterStudent(st5) << '\n' << '\n';

    // bool 타입 메소드 작동 확인
    cout << st1.isHigher(83) << '\n';
    cout << st3.isHigher(50) << '\n';
    cout << st4.isHigher(50) << '\n' << '\n';

    // 연산자 오버로딩 작동 확인
    vector<Student> book = vector<Student>();
    book.push_back(st1); book.push_back(st2); book.push_back(st3); book.push_back(st4); book.push_back(st5);

    sort(book.begin(), book.end());

    for (Student st : book) {
        cout << st.num << ' ' << st.name << ' ' << st.score << '\n';
    }

    return 0;
}

 

간단한 설명은 주석에 달았습니다.

 

추가로 연산자 오버로딩에 대해서는 부연 설명을 하겠습니다.

 

  • vector 자료구조에서 sort를 할 때, <연산자로 대소구분을 하여 정렬합니다.
  • C++에서는 클래스 타입에 대해 연산자를 어떻게 사용할지 명시하지 않으면 오류가 나므로 <연산자가 어떻게 작동될지 새로 명시합니다.
  • <연산자를 오버로딩하여 score로 비교함을 알림으로써 명시할 수 있습니다.

[Python]

 

 

import sys

br = sys.stdin
bw = sys.stdout

class Student:
    
    # 생성자 (필드가 따로 없음)
    def __init__(self, name, num, score):
        self.name = name
        self.num = num
        self.score = score

    # 객체를 받아 현재의 학생과 비교하여 누구의 성적이 더 높은지 문자열로 반환하는 메소드
    def GreaterStudent(self, st):
        temp = ""
      
        if (self.score > st.score): temp = self.name
        elif (self.score < st.score): temp = st.name
        else: temp = "두학생의 성적이 같습니다."
      
        return temp
    
    # 정수 N를 받아 현재 학생의 성적이 N보다 높은지를 boolean으로 반환하는 메소드
    def IsHigher(self, N):
        if (self.score > N): return True
        else: return False

    # 객체끼리의 우선순위를 정하기 위해 <연산자 오버로딩
    def __lt__(self, st):
        if (self.score == st.score): return self.num < st.num
        return self.score > st.score   
        

# 생성자로 객체 생성
st1 = Student("박형기", 4, 83)
st2 = Student("이건우", 2, 83)
st3 = Student("박세인", 3, 18)
st4 = Student("김현진", 5, 1000)
st5 = Student("강지훈", 1, 33)

# GreaterStudent 작동 확인
bw.write(st1.GreaterStudent(st2) + '\n')
bw.write(st2.GreaterStudent(st3) + '\n')
bw.write(st4.GreaterStudent(st5) + '\n' + '\n')

# IsHigher 작동 확인
bw.write(str(st1.IsHigher(83)) + '\n')
bw.write(str(st3.IsHigher(50)) + '\n')
bw.write(str(st4.IsHigher(50)) + '\n' + '\n')

# 연산자 오버로딩 작동 확인
book = []

book.append(st1)
book.append(st2)
book.append(st3)
book.append(st4)
book.append(st5)

book.sort()

for st in book:
    bw.write(str(st.num) + ' ' + st.name + ' ' + str(st.score) + '\n')

bw.close()
br.close()

 

간단한 설명은 주석에 적었습니다.

 

연산자 오버로딩에 관한 내용은 함수명만 차이가 있고 C++과 동일합니다.