이전 시간에 등장했던 static
에 대해 알아보자.
그리고, 생성자
와 this
에 대해 알아보고 이것을 응용해서 적용해보자!
클래스 Foo
를 만들고, 그 안에는 두가지의 변수를 줄 것이다.
static String classVar="I class var"
String instanceVar="I instance var"
클래스의 소속인 classVar
과, 인스턴스 소속인 instanceVar
이다.
class Foo{
public static String classVar="I class var";
public String instanceVar="I instance var";
}
public class StaticApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Foo.classVar); //OK
System.out.println(Foo.instanceVar); //Error
}
}
여기서 보면, Foo.classVar
는 에러가 나지 않지만,
Foo.instanceVar
는 에러가 나는 것을 알 수 있다. 즉, instanceVar
는 인스턴스를 통해서 사용하도록 고안된 변수다는 것을 알 수 있다.
classMethod()
라는 함수를 만들고, 그 안에서 테스트를 해보자.
class Foo{
public static String classVar="I class var";
public String instanceVar="I instance var";
public static void classMethod() {
System.out.println(classVar); //Ok
System.out.println(instanceVar); //Error
}
}
public class StaticApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Foo.classVar);
// System.out.println(Foo.instanceVar);
}
}
classMethod()
안에서 classVar
는 접근이 가능하나 instanceVar
는 접근이 안돼서 오류가 뜨는 것을 확인할 수 있다.
이번엔 instanceMethod()
를 만들어보고 위와 똑같은 내용으로 채워보자.
class Foo{
public static String classVar="I class var";
public String instanceVar="I instance var";
public static void classMethod() {
System.out.println(classVar); //Ok
// System.out.println(instanceVar); //Error
}
public void instanceMethod() {
System.out.println(classVar); //Ok
System.out.println(instanceVar); //Ok
}
}
public class StaticApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Foo.classVar);
// System.out.println(Foo.instanceVar);
}
}
classMethod()
와 다르게 instanceMethod()
에서는 둘다 에러가 나지 않는다.
이제 메소드에 접근
을 해보자.
public class StaticApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Foo.classVar);
// System.out.println(Foo.instanceVar);
Foo.classMethod(); //ok
Foo.instanceMethod(); //error
}
}
Foo.classMethod()
는 에러가 없지만, Foo.instanceMethod()
는 에러가 난다. 인스턴스 메소드는 인스턴스 소속이기 때문에, 클래스를 통해서 접근하는 것은 금지되어있다!
이제 인스턴스를 생성해보자.
Foo f1=new Foo();
여기서, 생성한 인스턴스 f1
에 있는 classVar
과 클래스 Foo
의 classVar
는 링크되어있다. 서로 값이 변경되면 서로가 영향을 받는 것이다.
그러나 instanceVar
는 서로 링크되어있지 않아 영향을 받지 않는다.
그리고 메소드도 똑같이 생각하면 된다!
class Foo{
public static String classVar="I class var";
public String instanceVar="I instance var";
public static void classMethod() {
System.out.println(classVar); //Ok
// System.out.println(instanceVar); //Error
}
public void instanceMethod() {
System.out.println(classVar); //Ok
System.out.println(instanceVar); //Ok
}
}
public class StaticApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Foo.classVar);
// System.out.println(Foo.instanceVar);
Foo.classMethod();
// Foo.instanceMethod();
Foo f1=new Foo();
Foo f2=new Foo();
System.out.println(f1.classVar); //I class var
System.out.println(f1.instanceVar); // I instance var
f1.classVar="changed by f1";
System.out.println(Foo.classVar); //changed by f1
System.out.println(f2.classVar);//changed by f1
f1.instanceVar="changed by f1";
System.out.println(f1.instanceVar); //changed by f1
System.out.println(f2.instanceVar); //I instance var
}
}
해당 소스코드를 보고, 하나하나 따져보도록 하자!
f2
인스턴스를 생성하자.
그리고 f1
으로 classVar
에 접근을 해보자.
그러면 클래스 Foo
의 classVar
를 가리키므로 I class var
를 출력한다.
f1
의 instanceVar
는 클래스에 셋팅된 기본 값인 I instance var
가 복제된 상태이기 때문에 f1.instanceVar
는 I instance var
가 출력이 된다.
f1.classVar="changed by f1"
로 값을 바꾸면 static
이기 때문에 클래스 Foo
의 classVar
값이 변하게 된다.
Foo.classVar
와 f2.classVar
를 하면 둘다 changed by f1
으로 출력이 된다.
f1.instanceVar="changed by f1"
을 통해 instanceVar
의 값을 바꾸면 f1
은 자신의 instanceVar
를 바꾼 것이기 때문에, f2
의 instanceVar
값은 바뀌지 않는다.
OthersOOP.java
를 살펴보자. (이전시간의 다른 이의 클래스와 인스턴스)
여기서, FileWriter f1=new FileWriter("data.txt")
에서,
인스턴스를 생성하는 시점에 "data.txt"
는 꼭 들어가야 한다.
인스턴스가 생성될 때, 또는 초기값을 주고 싶을 때 생성자
라는 것을 이용한다.
MyOOP.java
를 보자.
여기에서 사용자는 구분자를 주는 것을 깜빡하기가 쉽다.
그러므로 인스턴스를 생성할 때, delimiter값을 지정하지 않으면 인스턴스 화 되지 못하도록 해보자.
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();
}
}
원하는 건 이렇게 되는 것이다!
Java에서 클래스의 이름과 똑같은 메소드
를 정의하면 그것이 바로 생성자
이다.
class Print{
public String delimiter="";
public Print(String _delimiter) {
delimiter=_delimiter;
}
public void A() {
System.out.println(delimiter);
System.out.println("A");
System.out.println("A");
}
public void B() {
System.out.println(delimiter);
System.out.println("B");
System.out.println("B");
}
}
매개변수를 통해 들어온 구분자의 값이 해당 클래스 안에서 변수인 delimiter
값이 변경하게 된다.
class Print{
public String delimiter="";
public Print(String delimiter) {
delimiter=delimiter;
}
public void A() {
System.out.println(delimiter);
System.out.println("A");
System.out.println("A");
}
public void B() {
System.out.println(delimiter);
System.out.println("B");
System.out.println("B");
}
}
만약 _delimiter
에서 _
를 빼면, Print()
생성자 안에 있는 앞 뒤의 delimiter
는 둘다 매개변수
delimiter
를 가리킨다.
실행시키면 구분자 없이 출력된다.
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");
}
}
this
는 우리가 생성한 인스턴스
를 가리키는 이름이다.
즉, 인스턴스의 delimiter 변수
를 가리키는 것이다.
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.java
에 클래스와 인스턴스를 도입해보자!
Accounting
이라는 클래스를 만들어보자.
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());//소비자가낼돈
}
}
Accounting
클래스에 부가가치세랑 관련된 메소드와 변수들을 모아두었다.
그러면 이제, valueOfSupply
에 접근하려면 클래스명.변수명
으로 접근하고, 메소드에 접근하려면 클래스명.메소드명
으로 접근하면 된다.
만약,공급가가 만원일때와, 2만원일때를 번갈아가며 출력해야 한다고 가정해보자.
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); //공급가
Accounting.valueOfSupply = 20000.0;
System.out.println("Value of supply : "+Accounting.valueOfSupply); //공급가
Accounting.valueOfSupply = 10000.0;
System.out.println("VAT : "+Accounting.getVAT()); //부가가치세
Accounting.valueOfSupply = 20000.0;
System.out.println("VAT : "+Accounting.getVAT()); //부가가치세
Accounting.valueOfSupply = 10000.0;
System.out.println("Total : "+Accounting.getTotal());//소비자가낼돈
Accounting.valueOfSupply = 20000.0;
System.out.println("Total : "+Accounting.getTotal());//소비자가낼돈
}
}
두개의 상태만으로도 아주아주 끔찍해진다.
행복해지기 위해 인스턴스를 도입하자!
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());
}
}
인스턴스 a1
과 a2
를 도입해서 편해졌다.
그러면 Accounting
클래스는 어떻게 변해야 할까?
class Accounting{
public double valueOfSupply;
//vatRate는 어떤 인스턴스간에 동일하므로 instance 소속보단 클래스 소속이 더 나음
public static double vatRate = 0.1;
public double getVAT() {
return valueOfSupply*vatRate;
}
public double getTotal() {
return valueOfSupply+getVAT();
}
}
짜자잔~
인스턴스가 생성될 때 valueOfSupply
를 넣도록 바꿔보자!
즉, 생성자를 도입해보자~
class Accounting{
public double valueOfSupply;
public static double vatRate = 0.1;
public Accounting(double valueOfSupply) {
this.valueOfSupply=valueOfSupply;
}
public double getVAT() {
return this.valueOfSupply*vatRate;
}
public double getTotal() {
return this.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("Total : "+a1.getTotal());
System.out.println("Total : "+a2.getTotal());
}
}
코드가 좀 더 간결해졌다!
깔끔해서 이쁘다 :)
다음은 상속
에 대해서 배워보자!
JAVA강의가 얼마 남지 않았당..