Java/Java로 배우는 자료구조

자료구조 2-2. 메서드와 생성자

성장코딩 2023. 2. 13. 16:48

클래스는 서로 관련있는 데이터들을 하나의 단위로 묶어두기 위한 것이라고 설명할 수 있다. 하지만, 이것이 전부가 아니다.

서로 다른 데이터들뿐 아니라 그 데이터와 관련이 깊은 메서드함께 묶어둘 수 있다.

그 결과 서로 관련성이 높은 것들끼리 하나의 단위로 묶여있게 되고 이는 코드의 응집도(cohesion)를 높이게 된다.

반면, 클래스 간의 연결성은 느슨해지게 되므로 코드의 결합도(coupling)를 낮출 수 있다.

그 결과 어떤 장점이 있는가?

코드를 수정해야 할 때, main 메서드가 존재하는 클래스를 수정하는 것을 최소화하고, 각각의 클래스들이 나뉘어 있으므로 해당 클래스에서 수정해주면 되기 때문에 유지보수가 용이하다는 장점이 있다.

 

 

클래스에 포함된 데이터와 메서드는 어떤 의미를 가질까?

객체지향 프로그래밍에서 객체란 "데이터"와 "메서드"의 집합이라고 말할 수 있다. 데이터는 객체의 "정적" 속성을 표현하며, 메서드는 객체의 "동적" 속성(기능)을 표현한다.

예컨대, 클래스를 자전거에 비유했을 때,  자전거는 "모양, 무게, 크기, 브랜드" 등의 정적 속성(데이터)과 "달린다, 정지한다, 뒤로간다" 등의 기능을 가지게 된다.

 

Theme. 생성자

 

클래스 안에 그 클래스와 동일한 이름을 가지며 return 타입이 없는 특별한 메서드를 둘 수 있다. 이것을 생성자(constructor)라고 부른다.

생성자는 new 명령으로 객체가 생성될 때 자동으로 실행된다. 주 목적은 객체의 데이터 필드의 값을 초기화하는 것이다.

생성자가 반드시 매개변수를 받아야하는 것은 아니다. 

 

 

이전 게시물에서 직사각형에 대한 정보를 입력받아 면적을 기준으로 정렬하여 출력한 예제를 생성자를 활용하여 보다 효율적으로 코드를 작성해보고자 한다.

 

1. 왼쪽 위 점을 나타내는 MyPoint2 class

 

1
2
3
4
5
6
7
8
9
10
11
12
package section2;
 
public class MyPoint2 {
    public int x;
    public int y;
    
    public MyPoint2(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
 
cs

 

2. 직사각형 하나에 대한 데이터와 메서드를 나타내는 MyRectangle2 class

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package section2;
 
public class MyRectangle2 {
    public MyPoint2 lu;
    public int width;
    public int height;
    
    public MyRectangle2(int x, int y, int w, int h) {
        lu = new MyPoint2(x, y);
        width = w;
        height = h;
    }
    
    public int calArea() {
        return width * height;
    }
    
    public String toString() {
        return "(" + lu.x + ", " + lu.y + ") " + width + " " + height + " ";
    }
    
    
}
 
cs

 

3. main class

 

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package section2;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
 
public class Code05 {
 
    static MyRectangle2[] rects = new MyRectangle2[100]; // 사각형들의 배열
    static int n = 0// 배열에 저장된 사각형의 개수 n
 
    public static void main(String[] args) {
 
        try {
            Scanner sc = new Scanner(new File("data.txt"));
 
            while (sc.hasNext()) {
                int x = sc.nextInt();
                int y = sc.nextInt();
                int w = sc.nextInt();
                int h = sc.nextInt();
 
                rects[n] = new MyRectangle2(x, y, w, h);
                n++;
            }
            sc.close();
        } catch (FileNotFoundException e) {
            System.out.println("No data file.");
            System.exit(1); // 프로그램 종료
 
        }
 
        bubbleSort();
 
        for (int i = 0; i < n; i++) {
            System.out.println(rects[i].toString());
        }
 
    }
 
    public static void bubbleSort() {
        for (int i = n - 1; i > 0; i--) {
            for (int j = 0; j < i; j++) {
                if (rects[j].calArea() > rects[j+1].calArea()) {
                    MyRectangle2 tmp = rects[j + 1];
                    rects[j + 1= rects[j];
                    rects[j] = tmp;
                }
            }
        }
 
    }
 
}
 
cs

 

아래 예제를 해결해보자.

1. MyPoint2 class

 

1
2
3
4
5
6
7
8
9
10
11
12
package section2;
// 한 점에 대한 class
public class MyPoint2 {
    public int x;
    public int y;
    
    public MyPoint2(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
 
cs

 

 

2. OrthoLine class

 

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package section2;
// 평면 상의 하나의 수직(수평) 선분을 나타내는 class
public class OrthoLine {
 
    // 선분을 만들기 위한 두 점(선분의 양 끝점)을 선언
    public MyPoint2 u;
    public MyPoint2 v;
    
    public OrthoLine( MyPoint2 p, MyPoint2 q) {
        u = p;
        v = q;
        // 수직 선분의 경우 위쪽이 u, 아래쪽이 v
        // 수평 선분의 경우 왼쪽이 u, 오른쪽이 v가 되도록 해주었다.
        if(p.x > q.x || (p.x == q.x && p.y > q.y)) {
            swap();
        }
    }
    
    public void swap() {
        MyPoint2 tmp = u;
        u = v;
        v = tmp;
    }
    
    public OrthoLine( int x1, int y1, int x2, int y2) {
        u = new MyPoint2(x1, y1);
        v = new MyPoint2(x2, y2);
    }
    
    // 두 선분이 교차하는가?(수직, 수평 선분만 존재한다고 가정)
    // 메서드를 OrthoLine class에 정의하였으므로 다른 선분과의 교차여부만 파악하면 된다.
    public boolean intersects( OrthoLine other ) {
        // 내가 수직, other는 수평 선분
        if(isVertical() && !other.isVertical()) {
            return (u.x > other.u.x && u.x < other.v.x && u.y < other.u.y && v.y > other.u.y); // true면 교차하는 것
        }
        // 내가 수평, other는 수직 선분
        else if(!isVertical() && other.isVertical()) {
            return (u.x < other.u.x && v.x > other.u.x && u.y > other.u.y && u.y < other.v.y);
        }
        // 둘다 수직, 둘다 수평 선분
        else {
            return false// 두 선분은 만나지 않는다.
        }
        
    }
    // 수직 선분인지 여부
    public boolean isVertical() {
        return (u.x == v.x);
    }
    
    
    
    
    
    
}
 
cs

 

 

3. OrthoPolygon class

 

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
41
42
package section2;
 
// 하나의 직교다각형을 나타내는 class
public class OrthoPolygon {
    public int n = 0;
    public MyPoint2[] vertices;
 
    public OrthoPolygon(int k) {
        vertices = new MyPoint2[k]; // 꼭짓점 개수가 k인 다각형
    }
 
    // 꼭짓점을 추가
    public void addVertex(int x, int y) {
        vertices[n++= new MyPoint2(x, y);
    }
 
    // x좌표 중 가장 큰 x좌표를 구하는 메서드
    public int maxX() {
        int max = 0;
        for (int i = 0; i < n; i++) {
            if (vertices[i].x > max) {
                max = vertices[i].x;
            }
        }
        return max;
    }
 
    // 어떤 점이 다각형의 내/외부에 있는지 판단
    public boolean contains(MyPoint2 p) {
        OrthoLine arrow = new OrthoLine(p, new MyPoint2(maxX() + 1, p.y)); // 오른쪽 방향 수평선
        int count = 0;
        for (int i = 0; i < n; i++) {
            OrthoLine edge = new OrthoLine(vertices[i], vertices[(i + 1) % n]); // i가 n-1일 때는 다시 첫 번째 점(vertices[0])과
                                                                                // 연결돼야 하므로
            if (arrow.intersects(edge)) {
                count++;
            }
        }
        return (count % 2 == 1); // 교점의 개수가 홀수면 내부에 있는 것(짝수면 외부)
    }
}
 
cs

 

 

4. Code10

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
package section2;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
 
public class Code10 {
 
    public static void main(String[] args) {
        try {
            Scanner sc = new Scanner(new File("data.txt"));
            // 꼭짓점의 개수 입력받기
            int n = sc.nextInt();
            
            OrthoPolygon thePolygon = new OrthoPolygon(n);
            // 꼭짓점 좌표 순차적으로 입력 받기
            for (int i = 0; i < args.length; i++) {
                thePolygon.addVertex(sc.nextInt(), sc.nextInt());
            }
            // 테스트 할 점의 좌표 입력 받기
            MyPoint2 thePoint = new MyPoint2(sc.nextInt(), sc.nextInt());
            sc.close();
            if(thePolygon.contains(thePoint)) {
                System.out.println("내부에 위치!");
            }
            else {
                System.out.println("외부에 위치!");
            }
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.exit(1);
        } 
        
    }
 
}
 
cs

 

끝.