메소드
를 다른 컴퓨터 언어에서는 function
, subroutine
, procedural
이라고 한다.
절차지향 언어들에는 C
언어가 있다.
메소드만으로 프로그램을 만드는 것에 한계를 느낀 프로그래머들이
서로 연관된 메소드와 변수들을 그룹핑하고 그곳에 이름을 붙인게 class
이다. 그리고 클래스 중심으로 프로그램을 만드는 것을 객체지향 프로그래밍이라고 한다!
public class OthersOOP {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Math.PI);
System.out.println(Math.floor(1.8));
System.out.println(Math.ceil(1.5));
}
}
Math.PI
에서 Math
라는 클래스의 PI
라는 변수가 있는 것이고, 그 변수 안에 수(3.14...)가 저장되어있는 것이다.
Math.floor()
에서 floor()
는 내림을 해주는 Math
의 메소드이다.
Math.ceil()
에서 ceil()
은 올림을 해주는 메소드이다.
import java.io.FileWriter;
import java.io.IOException;
public class OthersOOP {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
System.out.println(Math.PI);
System.out.println(Math.floor(1.8));
System.out.println(Math.ceil(1.5));
FileWriter f1=new FileWriter("data.txt");
f1.write("Hello");
f1.write(" java");
f1.close();
}
}
이번에는 FileWriter
라는 클래스를 살펴보자. 파일에 쓰기를 할 때 쓰는 클래스이다. 해당 코드를 실행시키면 아래와 같은 결과가 출력된다.
FileWriter는 new
를 붙여서 f1
이라는 복제본을 생성하였다.
위의 소스코드에 아래 내용을 추가해보자.
FileWriter f2=new FileWriter("data2.txt");
f2.write("Hello");
f2.write(" java2");
f2.close();
실행시키면 data2.txt
가 생성되고, 그 안의 내용은 위와 같다.
Math 클래스처럼 일회용으로 작업을 하는 애들은 그냥 바로 클래스로 접근하면 되지만, FileWriter처럼 계속 사용하는 애들은 클래스를 복제해서 사용하는 것이다.
여기서 참고로, System
도 클래스이다!
class : System, Math, FileWriter
instance : f1, f2
public class MyOOP {
public static void main(String[] args) {
//..
System.out.println("----");
System.out.println("A");
System.out.println("A");
//..
System.out.println("----");
System.out.println("A");
System.out.println("A");
//..
}
}
여기서, 반복되는 것을 메소드
로 묶자.
그리고, printB()라는 메소드도 만들자!
public class MyOOP {
public static void main(String[] args) {
//..
printA();
printA();
printB();
printB();
}
public static void printA() {
System.out.println("----");
System.out.println("A");
System.out.println("A");
}
public static void printB() {
System.out.println("----");
System.out.println("B");
System.out.println("B");
}
}
그런데, 또 모종의 이유로 구분자를 다르게 해서 출력하고 싶어졌다고 생각하자.
같은 메소드를 여러번 반복하는 것은 비효율적이기 때문에, 매개변수
도입을 생각할 수 있다.
public class MyOOP {
public static void main(String[] args) {
//..
printA("----");
printA("----");
printB("----");
printB("----");
printA("****");
printA("****");
printB("****");
printB("****");
}
public static void printA(String delimiter) {
System.out.println(delimiter);
System.out.println("A");
System.out.println("A");
}
public static void printB(String delimiter) {
System.out.println(delimiter);
System.out.println("B");
System.out.println("B");
}
}
그런데 만약 구분자를 주는 메소드가 1억줄이 넘는다고 생각해보자..
끔찍하다! 그러므로 변수
를 도입하자.
public class MyOOP {
public static void main(String[] args) {
String delimiter="----";
printA(delimiter);
printA(delimiter);
printB(delimiter);
printB(delimiter);
delimiter="****";
printA(delimiter);
printA(delimiter);
printB(delimiter);
printB(delimiter);
}
public static void printA(String delimiter) {
System.out.println(delimiter);
System.out.println("A");
System.out.println("A");
}
public static void printB(String delimiter) {
System.out.println(delimiter);
System.out.println("B");
System.out.println("B");
}
}
이전과 출력은 똑같으면서, 한번에 구분자를 변경할 수 있는 폭발적인 효과를 가져올 수 있다.
하지만, 인자
를 주는 것이 싫다고 가정해보자.
public class MyOOP {
public static void main(String[] args) {
delimiter="----";
printA();
printA();
printB();
printB();
delimiter="****";
printA();
printA();
printB();
printB();
}
public static String delimiter="";
public static void printA() {
System.out.println(delimiter);
System.out.println("A");
System.out.println("A");
}
public static void printB() {
System.out.println(delimiter);
System.out.println("B");
System.out.println("B");
}
}
delimiter
변수를 이용하였다! 전역변수로 선언하여 메소드에서도 사용할 수 있도록 하였고, 또 printA()
의 인자도 없앴다.
delimiter
과 printA()
, printB()
를 Print
클래스로 묶고, Print.A()
또는 Print.B()
로 호출해보자.
class Print{
public static String delimiter="";
public static void A() {
System.out.println(delimiter);
System.out.println("A");
System.out.println("A");
}
public static void B() {
System.out.println(delimiter);
System.out.println("B");
System.out.println("B");
}
}
public class MyOOP {
public static void main(String[] args) {
Print.delimiter="----";
Print.A();
Print.A();
Print.B();
Print.B();
Print.delimiter="****";
Print.A();
Print.A();
Print.B();
Print.B();
}
}
Print
클래스를 통해 접근할 수 있다!
결과는 이전과 똑같지만 코드는 훨씬 더 단정해졌다.
클래스 안의 변수, 메소드를 통틀어서 멤버
라고 한다.
지금 Print클래스의 멤버는 delimiter
, A()
,B()
이다.
해당 소스코드를 저장하면, 이클립스에서는 위처럼 MyOOP.class
와 Print.class
가 생성된다.
생성했던 Print
클래스는 다른 .java
파일로 옮길 수 있다.
이사를 해주자!
public class MyOOP {
public static void main(String[] args) {
Print.delimiter="----";
Print.A();
Print.A();
Print.B();
Print.B();
Print.delimiter="****";
Print.A();
Print.A();
Print.B();
Print.B();
}
}
public class Print{
public static String delimiter="";
public static void A() {
System.out.println(delimiter);
System.out.println("A");
System.out.println("A");
}
public static void B() {
System.out.println(delimiter);
System.out.println("B");
System.out.println("B");
}
}
이렇게 구분하고, 실행시켜도 잘 동작한다!
이것도 메소드나 변수랑 마찬가지로 이클립스에서 지원해주는 Refactor
기능을 통해 Move Type To New File
을 통해 Print.java
파일을 한번에 생성할 수 있다! 완전 신기..
인스턴스는 위에 다른 이의 클래스와 인스턴스에서 FileWriter f1
에서 f1
에 해당한다.
public class MyOOP {
public static void main(String[] args) {
Print.delimiter="----";
Print.A();
Print.A();
Print.B();
Print.B();
Print.delimiter="****";
Print.A();
Print.A();
Print.B();
Print.B();
Print.delimiter="----";
Print.A();
Print.delimiter="****";
Print.A();
Print.delimiter="----";
Print.A();
Print.delimiter="****";
Print.A();
}
}
이렇게 변경해야 하는 일이 생겼다고 가정하자.
너무 비효율적이다! 이럴때 인스턴스
를 사용한다.
인스턴스를 생성할 때는
클래스명 인스턴스명 = new 클래스명();
으로 생성한다.
이전에 메소드(2)에서 static
은 클래스 소속이라고 하였다.
그러니, 인스턴스를 사용할 때는 static을 다 없애주자!
class Print{
public String 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");
}
}
Print.java
에서 static
을 다 없애버리자!
그리고 MyOOP.java
도 마찬가지로 수정해주자.
public class MyOOP {
public static void main(String[] args) {
Print p1=new Print();
p1.delimiter="----"; //instance's delimiter
p1.A();
p1.A();
p1.B();
p1.B();
Print p2=new Print();
p2.delimiter="****"; //instance's delimiter
p2.A();
p2.A();
p2.B();
p2.B();
p1.A();
p2.A();
p1.A();
p2.A();
}
}
소스코드가 아주 간결해졌다!
실행결과는 위에서 인스턴스 안썼을 때랑 똑같지만, 더 간결하다!