Java

생활코딩 JAVA 객체 지향 프로그래밍 - 생성자와 this / 클래스와 인스턴스의 활용 (+수업을 마치며)

소댓 2023. 1. 9. 11:06

 

7. 생성자와 this

 

- 생성자 : 어떤 클래스가 복제되었을 때(즉, 인스턴스가 생성되었을 때), 초기에 즉각적으로 바로 어떤 일이 처리되게 하거나, 어떤 값을 주입받도록 하기 위해 사용할 수 있는 유용한 메소드 기능

 

- FileWriter f1 = new FileWriter("data.txt");

> 위처럼 남의 클래스를 만들 때, FileWriter라는 클래스에 new를 붙여 인스턴스를 만듦

> class를 호출할 때 "data.txt"라는 값은 우리가 수정하고자 하는 파일의 이름

> 파일을 수정하는 행위를 나타내는 FIleWriter라는 클래스는 수정하고자 하는 대상이 꼭! 지정되어야 함

> 파일을 지정하는 행위를 까먹거나 나중에 하게 되면 문제가 생길 수 있기 때문에, 인스턴스를 생성하는 과정에 파일을 지정할 수 있다면, 클래스를 사용하는 사람이 대상이 되는 파일을 까먹지 않을 수 있음

> 인스턴스가 생성될 때 반드시 처리해야 할 작업이 있을 수 있는데, 그러한 초기값이나 최초에 꼭 필요한 작업을 하고 싶을 때 '생성자'라는 것을 사용함

 

- 예를 들어, 구분자인 delimiter 값을 꼭 셋팅해야 우리가 원하는 작업을 할 수 있을 때,

> 인스턴스를 생성할 때 delimiter값을 지정하지 않으면 우리가 만든 클래스가 인스턴스화 되지 못하도록 함

>> 사용자가 실수할 가능성을 원천적으로 봉쇄

 

- 클래스와 똑같은 이름의 메소드를 정의하면 그것이 바로 '생성자'

 

- This : 클래스가 인스턴스화 되었을 때, 인스턴스를 가르키는 특수한 이름(this.를 사용해서 구분)

 

 

 

8. 클래스와 인스턴스의 활용

 

8.1 활용 - 클래스화

 

- Accounting이라는 클래스 생성해서 정리

> Class라는 큰 틀을 만들어서 그 안에 Variable과 Method를 넣어서 코드를 사용하게 되면,

  Class에 지어진 이름으로 Variable과 Method가 어떤 부분에 사용하는지 알기 시우며

  xxx.total 등의 Method 이름이 중복되더라도 다른 Class(ccc.total)로도 이용이 가능함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Accounting{
        public static double valueOfSupply = 10000.0;
        public static double vatRate = 0.1;
        public static double getVAT() {
            return valueOfSupply * vatRate;
        }
        public static double getTotal() {
            return valueOfSupply + getVAT();
        }
}
    public class AccountingApp {
    public static void main(String[] args) {
        Accounting.valueOfSupply = 10000.0;
        System.out.println("Value of supply : " + Accounting.valueOfSupply);
        System.out.println("VAT : " + Accounting.getVAT());
        System.out.println("Total : " + Accounting.getTotal());
 
    }
 
}
cs

 

 

8.2 활용 - 인스턴스화

 

- 이렇게 Accounting이라는 하나의 클래스를 여러 상태가 돌려서 사용하는 경우의 코드를 정리한다면?

>> 인스턴스가 필요

 

 

 

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
class Accounting{
        public double valueOfSupply;
        public static double vatRate = 0.1;
        public double getVAT() {
            return valueOfSupply * vatRate;
        }
        public double getTotal() {
            return valueOfSupply + getVAT();
        }
}
    public class AccountingApp {
    public static void main(String[] args) {
        Accounting a1 = new Accounting();
        a1.valueOfSupply = 10000.0;
        
        Accounting a2 = new Accounting();
        a2.valueOfSupply = 20000.0;
        
        System.out.println("Value of supply : " + a1.valueOfSupply);
        System.out.println("Value of supply : " + a2.valueOfSupply);
        
        System.out.println("VAT : " + a1.getVAT());
        System.out.println("VAT : " + a2.getVAT());
        
        System.out.println("Total : " + a1.getTotal());
        System.out.println("Total : " + a2.getTotal());
 
    }
}
cs

(결과)

Value of supply : 10000.0
Value of supply : 20000.0
VAT : 1000.0
VAT : 2000.0
Total : 11000.0
Total : 22000.0

 

> vatRate(부가가치세율)은 어떤  instance던 동일하기 때문에 instance 소속 보다는  클래스 소속인 static으로 두는 것이 좋음(메모리를 사용하지 않아도 되어서 컴퓨터 자원 절약 가능)

> vatRate 값을 만약 0.2%로 바꾼다면 vatRate 값만 바꿔주면 vatRate를 사용하는 모든 인스턴스에서 한번에 바뀌는 유지보수의 편의성을 가질 수 있음

 

 

 

- 만약 valueOfSupply 값을 생성자 레벨에서 강제하고 싶다면? > Accounting 메소드 구현

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
class Accounting{
        public double valueOfSupply;
        public static double vatRate = 0.1;
        public Accounting(double valueOfSupply) {
            this.valueOfSupply = valueOfSupply;
        }
        public double getVAT() {
            return valueOfSupply * vatRate;
        }
        public double getTotal() {
            return valueOfSupply + getVAT();
        }
}
    public class AccountingApp {
    public static void main(String[] args) {
        Accounting a1 = new Accounting(10000.0);
        a1.valueOfSupply = 10000.0;
        
        Accounting a2 = new Accounting(20000.0);
        a2.valueOfSupply = 20000.0;
        
        System.out.println("Value of supply : " + a1.valueOfSupply);
        System.out.println("Value of supply : " + a2.valueOfSupply);
        
        System.out.println("VAT : " + a1.getVAT());
        System.out.println("VAT : " + a2.getVAT());
        
        System.out.println("Total : " + a1.getTotal());
        System.out.println("Total : " + a2.getTotal());
 
    }
}
cs

(결과)

Value of supply : 10000.0
Value of supply : 20000.0
VAT : 1000.0
VAT : 2000.0
Total : 11000.0
Total : 22000.0

 

 

9. 수업을 마치며

 

- Inheritance(상속)

> method1이라는 메소드를 가진 Parent라는 클래스를 직접 수정할 수 없을 때, method2를 추가하고 싶다면

  Parent라는 클래스 코드 전체를 카피해서 ClonedChild라는 클래스를 만들고 method2 추가

  이런 경우에 Parent의 method1을 수정하게 되면, Clonedchild의 코드를 하나 하나 다 수정해야 함

> 이럴 때 상속을 사용하면 > class Child extends Parent{

   child라는 클래스에는 실제로 method1이 구현되어있지 않지만,  

   상속을 받았기 때문에 Parent의 method1을 Child도 사용할 수 있음

   즉, method1이 수정되면 그것을 상속받는 모든 자식들의 method1이 수정됨

 

- interface : 콘센트에 전기가 들어올 때, 우리는 구현에는 관심이 없다. 단지 220V 규격, 즉 얼마를 입력해주는지만 관심

> 어떻게 규현했는지는 상관 없음. 어떤 값을 입력하는지에만 신경을 쓰면 됨

> Contract라는 interface를 Concreate1에서 구현하고자 할 때,

   Contract에 적혀있는 형태의 메소드를 구체적으로 구현해야 하는 책임을 갖게 됨

 

- Package : Foo라는 클래스를 다른 기능, 같은 이름의 다른 클래스가 있다면, 다른 이름의 패키지에 담음을 통해

> com.company1.Foo, com.company2.Foo처럼 같은 이름의 클래를 사용할 수 있음

> 즉 나눠진 클래스를 정리정돈하는 디렉토리로 사용하는 것이 '패키지', 자바에서 패키지보다 더 큰 틀은 존재하지 않음