안녕하세요! 쏘코입니다.

 

오늘은 생성자와 this에 대해서 알아보고, 지금까지 배운 내용을 바탕으로 활용해보는 시간을 가져보겠습니다!

 

목차


    0. 생성자와 this

    전에 만들었던 OthersOOP.java파일을 보면 FileWriter가 있죠?

    우리는 f1이라는 이름으로 FileWrtier 클래스의 인스턴스를 만들었습니다.

    그런데 new 뒤에 있는 FileWrtier에 매개변수가 있죠??

    이 FileWriter의 매개변수는 우리가 수정하고자 하는 파일의 이름입니다.

    만약 수정하고자 하는 파일의 이름이 없다면 프로그램이 정상적으로 작동할 수 없겠죠?

     

     

    특정 인스턴스가 작동하기 위해 특정 무언가가 반드시 필요하다면

    그 무언가는 생성이 될 때 이미 정의가 되어있어야 할 것입니다.

    인스턴스가 생성될 때 작동하는 것이 클래스의 생성자입니다.

     

    MyOOP.java에서는 인스턴스를 만들고 delimiter를 할당했죠?

    만약 delimiter가 할당이 되지 않는다면?

    공백 상태로 delimiter가 남아있을 것입니다.

    delimiter가 공백이라면 요소들이 정상적으로 구분이 되지 않을 수도 있겠죠?

    이런 경우를 방지하기 위해서 new Print()의 매개변수로 delimiter값을 받아야만 정상적으로 Print 형태의 인스턴스가 생성될 수 있도록 만들어보겠습니다.

     

    Before

     

    자바는 인스턴스를 생성할 때 클래스명과 같은 이름의 메소드가 있다면 그 메소드를 호출합니다.

    그리고 그 메소드를 생성자(Constructor)라고 부릅니다.

    생성자는 리턴 데이터 타입을 따로 지정하지 않아도 됩니다.

     

    인스턴스를 생성할 때 필요한 요소를 받아오고 싶다면 Print 생성자를 만들 때 매개변수를 받도록 만들면 되겠죠?

    그리고 그 받아온 매개변수를 이용해서 다양한 초기화 작업을 해 주고 싶다면 그 부분을 { } 안에 넣어주면 됩니다.

    필요한 부분만 남기고 주석처리를 하고 돌려보면 원하는 대로 출력이 되는 모습입니다.

     

    정상적으로 출력!!

     

    그런데 우리가 작성한 Print에서 매개변수 내의 _를 지워주면 어떻게 될까요?

    생성자에서 받아온 delimiter가 우선으로 선택되기 때문에 인스턴스변수인 delimiter는 변하지 않게 됩니다.

     

     

    이런 경우에 앞에 this를 붙이면 정상적으로 작동합니다.

    this는 바로 인스턴스의 이름을 가리키게 됩니다.

    this.delimiter라고 선언하게 되면 더 명확하게 인스턴스의 변수를 가리키는 것이라는 정보를 전달할 수 있겠죠?!

     

    // MyOOP.java
    
    public class MyOOP {
    	
    	public static void main(String[] args) {
    		Print p1 = new Print("----");
    		p1.A();
    //		p1.A();
    //		p1.B();
    //		p1.B();
    //		
    //		Print p2 = new Print("****");
    //		p2.A();
    //		p2.A();
    //		p2.B();
    //		p2.B();
    //		
    //		p1.A();
    //		p2.A();
    //		p1.A();
    //		p2.A(); 
    	}
    
    }
    // Print.java
    
    class Print {
    	public String delimiter = "";
    	public Print(String delimiter) {
    		this.delimiter = delimiter;
    	}
    	public void A() {
    		System.out.println(this.delimiter);
    		System.out.println("A");
    		System.out.println("A");
    	}
    	
    	public void B() {
    		System.out.println(this.delimiter);
    		System.out.println("B");
    		System.out.println("B");
    	}
    }

     


    1. OOP의 활용 0

    지금까지 배운 내용을 바탕으로 메소드 수업때 만들었던 AccountingApp을 수정해보도록 하겠습니다.

    새롭게 AccountingApp 클래스를 만들어줍니다. (만든 것을 재활용 하셔도 됩니다!)

    그리고 이전 AccountingApp의 내용을 복사해오거나, 메소드의 활용편에서 소스 코드를 긁어오시면 됩니다!

    귀찮으신 분들을 위해 아래에 소스 코드를 올려드립니다.

    조금 바뀐 부분이 있다면 main 메소드 내에서 valueOfSupply를 선언했습니다.

     

    public class AccountingApp {
    	// 공급가액
    	public static double valueOfSupply;
    	// 부가가치세율
    	public static double vatRate = 0.1;
    	
    	public static double getVAT() {
    		return valueOfSupply * vatRate;
    	}
    	
    	public static double getTotal() {
    		return valueOfSupply + getVAT();
    	}
    	
    	public static void main(String[] args) {
    		valueOfSupply = 10000.0;
    		System.out.println("Value of supply : " + valueOfSupply);
    		System.out.println("VAT : " + getVAT());
    		System.out.println("Total : " + getTotal());
    
    	}
    
    }

     

    물건의 원래 값과 부가가치세를 더한 값을 구하기 위한 프로그램, 기억나시죠!

     

    만약 AccountingApp에 다른 많은 변수와 메소드들이 존재한다면 관리하기가 어려워지겠죠?

    그래서 우리는 AccountingApp에서 부가가치세를 구하기 위한 변수와 메소드들을 따로 빼서 관리하고 싶습니다.

     

    AccountingApp 위에 Accounting이라는 새로운 클래스를 만들어줍니다.

    그리고 그 클래스 안에 부가가치세 계산과 관련된 부분을 모두 빼줍니다.

    이렇게 클래스로 따로 뺐으니, AccountingApp의 main 메소드에서 사용하기 위해서는 그 클래스의 이름을 적어줘야겠죠?

    클래스의 변수나 메소드를 사용하기 위해서는 그 클래스의 이름을 앞에 붙여줘야 합니다.

    Accounting.valueOfSupply = 10000.0;

    Accounting.getVAT();

    Accounting.getTotal();

    처럼 말이죠!

     

    이 작업만 해주면 우리는 깔끔하게 부가가치세 계산에 필요한 내용만을 다른 클래스로 분리해서 관리하고 사용할 수 있게 됩니다.

    추가로 이 작업을 통해 valueOfSupply, getVAT(), getTotal()라는 이름의 변수와 메소드가 중복되더라도 클래스가 다르면 구분해서 사용할 수 있습니다.

    훌륭하죠!!

     

    class Accounting{
    	// 공급가액
    	public static double valueOfSupply;
    	// 부가가치세율
    	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());
    
    	}
    
    }

     


    2. OOP의 활용 1

    이번에는 클래스인스턴스화 해보도록 하겠습니다.

     

    지금 우리가 만든 프로그램은 한번 세팅을 해 놓으면 그 값이 계속 유지되는 형식으로 되어있습니다.

    아래와 같은 상황에서는 굳이 인스턴스화를 할 필요가 없겠죠.

     

     

    하지만 10000원일 때의 공급가액을 출력하고, 20000원일 때의 공급가액을 출력한 뒤에

    다시 10000원일 때의 부가가치세를 출력하고, 20000원일 때의 부가가치세를 출력하고

    10000월일 때의 총 가격을 출력하고, 20000원일 때의 총 가격을 출력한다고 생각해봅시다.

     

     

    이렇게 계속 상태가 변하게 되면 valueOfSupply를 계속 바꿔줘야 하는 상황에 처하게 되겠죠?

    이럴 때 우리를 도와줄 수 있는 것이 바로 인스턴스입니다.

     

    인스턴스마다 고유한 상태를 주게 되면 좀 더 편하고 빠르게 동작하는 프로그램을 만들 수 있겠죠?

    a1과 a2라는 Accounting 클래스의 인스턴스를 만들면 a1과 a2라는 독립적인 공간에 valueOfSupply가 저장됩니다.

    우리는 이제 사용만 하면 되겠죠!

    여기서 vatRate는 변화하지 않기 때문에 static으로 내버려두는 것이 더 좋을 수 있습니다.

    static은 한 클래스에 단 하나만 존재하는데, vatRate는 단 하나만 존재한다는 조건에 맞죠?

    (한 국가에서 부가가치세율은 하나 뿐이니까!!) 

     

     

    여기서 좀 더 발전시켜봅시다.

    우리는 인스턴스를 생성하고 나서 각 인스턴스에 valueOfSupply를 할당해줬죠?

    하지만 클래스에서 생성자를 만들고 생성자의 매개변수로 valueOfSupply를 받아온다면 두 줄을 한 줄로 줄일 수 있습니다.

     

    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);
    		
    		Accounting a2 = new Accounting(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("VAT : " + a1.getTotal());
    		System.out.println("VAT : " + a2.getTotal());
    
    	}
    
    }

     


    많은 학습자들이 객체 지향에서 포기합니다.

    하지만 객체 지향이 없더라도 자바를 이용해서 문제를 해결할 수 있습니다.

    객체 지향이 너무 어렵다면 급하게 정면돌파 하려고 하지 마시고 객체 지향 없이 문제를 해결해보세요.

    그리고 코드가 충분히 복잡해지면 그 때 객체 지향의 필요성에 대해서 좀 더 쉽게 이해할 수 있을 것이고, 그 때 하는 공부는 지금보다 훨씬 더 유익하게 다가올 것입니다.

     

    객체지향을 이해하셨다면 상속에 대한 공부로 이어가시면 좋을 것 같습니다.

    클래스와 인스턴스, 상속은 뗄레야 뗼 수 없는 관계거든요.

     

    그렇다면 다음 포스팅부터는 상속에 대해서 작성해 보도록 하겠습니다!

    읽어주셔서 감사합니다!! 🙂🙂

     

     

    반응형
    • 네이버 블로그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기