Test105~Test108
※ 앞에서 확인해 본 Selection Sort(Test103) 나 Bubble Sort(Test104)의 성능은 같다.
(-> 반복의 획수로 추정)
하지만, 향상된 Bubble Sort는 대상 데이터의 구조에 따라서
일단 Bubble Sort 나 Selestion Sort 보다 성능이 좋을 수 있다.
원본 데이터 : 61 15 20 22 30
15 20 22 30 61 - 1회전 (스왑 발생 -> true) -> 다음 회전 진행 ○
15 20 22 30 61 - 2회전 (스왑 발생 -> false) -> 다음 회전 진행 X
==> 1회전 수행...2회전 수행...을 해보았더니
2회전에서 스왑(자리바꿈)이 전혀 일어나지 않았지 대문에
불필요한 추가 연산(더 이상의 회전)은 무의미한 것으로 판단하여
수행하지 않는다.
// 실행 예)
// Source Data : 10 50 20 30 40
// Sorted Data : 10 20 30 40 50
// 계속하려면 아무키나 누르세요...
public class Test105
{
public static void main(String[] args)
{
int[] a = {10, 50, 20, 30, 40};
/*
10 50 20 30 40 0 1
== --
10 20 50 30 40 1 2
== --
10 20 30 50 40 2 3
== --
10 20 30 40 50 3 4
== --
---------------------------- 1회전 -> 스왑 발생
10 20 30 40 50 0 1
== --
10 20 30 40 50 1 2
== --
10 20 30 40 50 2 3
== --
---------------------------- 2회전 -> 스왑 발생하지 않음
X
X
---------------------------- 3회전 -> X
X
---------------------------- 4회전 -> X
*/
System.out.print("Source Data : ");
for(int n : a)
System.out.print(n + " ");
System.out.println();
boolean flag;
int temp;
int pass=0;
do
{
flag = false;
pass++;
int i=0;
for (i=1; i<a.length-pass; i++)
{
//테스트
//System.out.print(i + "쑝");
if (a[i]>a[i+1]) // 01 12 23 34
// 01 12 23
// 01 12
// 01
{
//자리바꾸기
temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
flag = true;
//-- 단 한 번이라도 스왑(자리바꿈)이 발생하게 되면
// flag 변수는 true로 변경~!!!
}
}
System.out.println("웅~!!"); //2회전 웅 웅~
}
while (flag);
//-- flag 변수가 false라는 것은
// 회전이 구분적으로 발생하는 동안 스왑이 일어나지 않은 경우로
// 더 이상의 반복문 수행은 무의미한 것으로 판단 가능~!!!
/*----------------------------------------------------------------------
int i=0;
for (i=1; i<a.length; i++)
{
flag = false;
for (int j=0; j<a.length-i;j++)
{
if (a[j]>a[j+1])
{
a[j] = a[j]^a[j+1];
a[j+1] = a[j+1]^a[j];
a[j] = a[j]^a[j+1];
flag = true;
}
//테스트
System.out.print(j + " ");
if(j==a.length-i-1 && flag==false)
break;
}
}
-------------------------------------------------------------------*/
System.out.print("Sorted Data : ");
for(int n : a)
System.out.print(n + " ");
System.out.println();
}
}
/*
Source Data : 10 50 20 30 40
웅~!!
웅~!!
Sorted Data : 10 20 30 40 50
계속하려면 아무 키나 누르십시오 . . .
*/
//삽입, 힙, 쉘 정렬도 찾아서 구현해보기!!
// 사용자로부터 여러 학생의 성적 데이터를 입력받아
// 점수가 높은 순에서 낮은 순으로 등수를 부여하는
// 결과를 출력하는 프로그램을 구현한다.
// 단, 배열과 정렬 알고리즘을 활용하여 작성할 수 있도록 한다.
// 실행 예)
// 인원 수 입력 : 5
// 이름 점수 입력(1) : 정효진 90
// 이름 점수 입력(2) : 김연경 80
// 이름 점수 입력(3) : 김희진 85
// 이름 점수 입력(4) : 염혜선 75
// 이름 점수 입력(5) : 양효진 95
/*
-------------------
1등 양효진 95
2등 정효진 90
3등 김희진 85
4등 김연경 80
5등 염혜선 75
------------------
계속하려면 아무 키나 느르세요...
*/
import java.util.Scanner;
public class Test106
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int n;
int i=0, j;
//boolean flag;
System.out.print("인원 수 입력 : ");
n = sc.nextInt();
String name[] = new String[n];
int score[] = new int[n];
for (i=0; i<n; i++)
{
System.out.printf("이름 점수 입력(%d) : ",i+1);
name[i] = sc.next();
score[i] = sc.nextInt();
}
String temp=" ";
// 선택정렬
for (i=0; i<n-1; i++)
{
for (j=i+1; j<n; j++)
{
if (score[i]<score[j])
{
score[i] = score[i]^score[j];
score[j] = score[j]^score[i];
score[i] = score[i]^score[j];
temp = name[i];
name[i] = name[j];
name[j] = temp;
}
}
}
/*
// 버블정렬
int k;
for (i=1; i<n; i++)
{
for (j=0,k=0;j<n-1;j++)
{
if (score[j]>score[j+1])
{
score[j] = score[j]^score[j+1];
score[j+1] = score[j+1]^score[j];
score[j] = score[j]^score[j+1];
temp = name[j];
name[j] = name[j+1];
name[j+1] = temp;
k++;
}
}
}
*/
int rank[] = new int[n];
for (i=0; i<n; i++)
{
rank[i] = 1;
for (j=0; j<n;j++ )
{
if (score[i]<score[j])
{
rank[i]++;
}
}
}
// 결과 출력
System.out.println("--------------");
for (i=1; i<=n; i++)
{
System.out.printf("%d등 %s %d\n",rank[i-1],name[i-1],score[i-1]);
}
System.out.println("--------------");
}
}
/*
인원 수 입력 : 3
이름 점수 입력(1) : 정효진 98
이름 점수 입력(2) : 김연경 55
이름 점수 입력(3) : 김희진 87
--------------
1등 정효진 98
2등 김희진 87
3등 김연경 55
--------------
계속하려면 아무 키나 누르십시오 . . .
*/
오버라이딩은 상속에만 존재한다.
새로 설계(생성)하고자 하는 클래스가
이미 설계되어 있는 다른 클래스의 기능과 중복되는 경우
이미 설계된 클래스의 일부분이나 전체 구조를 공유할 수 있도록 하는 기능을 의미한다.
즉, 상속은 객체를 좀 더 쉽게 만들 수 있는
고수준의 '재사용성(reusability)'을 확보하고
객체간의 관계를 구성함으로써
객체 지향의 또 다른 큰 특징인 『다형성』의 문법적 토대가 된다.
상속은 기존 프로그램의 클래스 내용을 공유함으로써
중복된 코드들을 재작성할 필요 없이
반복적이고 세부적인 작업을 처리하지 않기 때문에
프로그램을 작성하는 시간을 절약할 수 있고
유지보수를 편리하게 할 수 있으며,
프로그램의 길이도 짧아지게 된다.
또한, 이미 작성된 프로그램들은 앞서 테스트되었기 때문에
오류를 줄일 수 있어 현재 작성중인 프로그램에만 전념할 수 있다.
(재사용은 10개중 1개정도만 이렇게씀)
※ 주의할 점
자바는 다.중.상.속을 지원하지 않기 때문에
두 개 이상의 클래스로부터 상속받을 수 없다.(부모는 하나여야함)
상위 클래스 == 부모 클래스 == 조상 클래스 == Super 클래스 -> 물려 주는 클래스
하위 클래스 == 자식 클래스 == 자손 클래스 == Sub클래스 -> 물려 받는 클래스 (대상 결정)
자바에서 상속은 부모(A)를 내가 골라(B)
실무에서는 코드의 재사용성보다 다른 관점(가이드형태)으로 더 많이 쓴다
(재사용은 10개중 1개정도만 이렇게씀)
a는 스포츠카 엔진 b는 클래식카 인데 엔진을 공유하는건 의미없음
전화기를 만든다 치면 이런식으로 만들어라~ 하는 가이드 형태(규칙)로 상속이라는 문법을 실무에서 씀
static 으로 선언되지 않은 메소드에서 사용되며
현재 클래스가 상속받은 상위 클래스의 객체를 가리킨다.
super 는 상위 클래스의 생성자를 호출하거나,
상위 클래스의 멤버 변수 또는 메소드를 호출할 때 사용할 수 있다.
하위 클래스의 생성자에서 상위 클래스의 생성자를 호출할 때에는
하위 클래스의 생성자 정의 구문에서 맨 처음에만 위치할 수 있다.
(이건... 상속의 문법이 아니라... 앞에서 공부한 생성자의 기본적인 문법~!!!)
// 부모 클래스
class SuperTest107
{
protected double area;
// 부모 클래스 생성자
SuperTest107()
{
System.out.println("Super class...");
}
void write(String title)
{
System.out.println(title + " - " + area);
}
}
// 자식 클래스
// ※ 자바는 단일 상속만 지원되며, 다중 상속은 허용하지 않는다.
// 자식입장에서 보는 것!! 부모는 몇개의 클래스에 상속해도 됨!
public class Test107 extends SuperTest107//, SuperTest108, SuperTest109 -- 이게 안되는 것!
{
/* 상속받으면 이렇게 적히진않지만 이렇게 상속됨 생성자 제외됨!
protected double area; <---이 area는 super.area!!
void write(String title)
{
System.out.println(title + " - " + area);
}
*/
//double area = 10.1234; //-- 자식의 입장에서 area는 2개 이것과 proteccted double area 물려받은것
// 자식 클래스 생성자
Test107()
{
// 부모 클래스 생성자 호출
// SuperTest107(); // this(); -> Test107(); ==> super 키워드쓰면 상속받는 클래스!! -> SuperTest107
//super(); //--> SuperTest107
System.out.println("Sub class...");
//super(); //--> SuperTest107
//--===>> 에러 발생(컴파일 에러)
}
// 생성자 안에서 또 다른 생성자를 부르는 것
// -> 하지만 생성자가 또다른 생성자를 호출한다는건 생성자 내부에서 가장 먼저 실행되어야 함!!
public void circle()
{
int r = 10;
area = r * r * 3.141592;
write("원");
}
public void rect()
{
int w=20, h=5;
area = w * h;
//-- SuperTest107.area = w * h;
write("사각형");
//-- SuperTest107.write("사각형")
}
public static void main(String[] args)
{
// Test107 클래스(자식) 기반 인스턴스 생성 -> 이때 자식기반의 클래스 생성자가 이루어짐 -> 이 과정에서 자식은 우리 눈에 보이지 않지만 부모클래스의 생성자 호출도 포함되어있음
Test107 ob = new Test107();
ob.circle();
//--==>> 원 - 314.1592
ob.rect();
//--==>> 사각형 - 100.0
}
}
// 하위 클래스는 상위 클래스의 멤버를 상속받지만,
// 생성자는 상속 대상에서 제외된다.
// 그리고, 하위 클래스의 생성자가 호출될 때
// 자동으로 상위 클래스의 생성자가 호출된다.
// 이 때, 호출되는 상위 클래스의 생성자는
// 인수가 없는 생성자(default 생성자 형태)가 된다.
// 상위 클래스 및 하위 클래스를 설계하는 과정에서
// 상위 클래스의 생성자를 정의하지(작성하지) 않거나
// 명시적으로 하위 클래스에서 상위 클래스의 생성자를 호출하지 않아도
// 상위 클래스에 인자가 있는 생성자만 존재하는 경우에는
// 주의해야 한다.
// 예를 들어 다음에서.....
/*
class A_class
{
A_class(int n)
{
}
}
class B_class extends A_class
{
B_class()
{
super();
}
}
*/
// 하위 클래스인 B_class의 생성자에서
// 명시적으로 A_class 의 생성자를 호출하지 않으면
// 자동으로 인자 없는 생성자를 호출한다.
// 하지만, A_class 에는 인자가 있는 생성자만 존재하고
// 인자가 없는 생성자는 존재하지 않기 때문에 에러 발생한다.
// 따라서, B_class생성자의 선두에
// 다음처럼 명시적으로 상위 클래스의 생성자 호출 구문을 작성해야 한다.
/*
class A_class
{
A_class(int n)
{
}
}
class B_class extends A_class
{
B_class()
{
super(10);
...
...
}
}
*/
[■ 정리 ■]
=================================================================================================================================
상위 클래스 | 하위 클래스 | 결과
---------------------------------------------------------------------------------------------------------------------------------
생성자를 | 생성자 정의 안함 |→ 가능하다.(아무일도 일어나지 않는다.)
정의하지 | 인수가 없는 생성자 |→ 가능하다.(디폴트가 자동으로 생성)
않은 | 인수가 있는 생성자 |→ 가능하다.(인수안에 자동으로 super() 데려와서 디폴트 자동으로 생성해서 가능함)
----------------------------------------------------------------------------------------------------------------------------------
인수가 | 생성자 정의 안함 |→ 가능하다.
없는 | 인수가 없는 생성자 |→ 가능하다.
생성자만 정의 | 인수가 있는 생성자 |→ 가능하다.
----------------------------------------------------------------------------------------------------------------------------------
인수가 | 생성자 정의 안함 |→ 에러 발생. (생성자 반드시 정의 해야함)
있는 | 인수가 없는 생성자 |→ 상위 클래스의 해당 생성자(인수가 있는 생성자)를 호출하지 않으면 에러 발생.
생성자만 정의 | 인수가 있는 생성자 |→ 상위 클래스의 해당 생성자(인수가 있는 생성자)를 호출하지 않으면 에러 발생.
=================================================================================================================================
// Rect108 클래스와 Circle108 클래스의 부모 클래스
class SuperTest108
{
protected double area; // protected를 썻다!? -> 이거는 거의 상속을 염두해도 만들었다고 봐도 됨
private String title; // 프라이베잇은 자식이 접근을 못함!
//부모 클래스의 인자없는 사용자 정의 생성자
public SuperTest108()
{
System.out.println("SuperTest108... 인자 없는 생성자");
}
//부모 클래스의 문자열을 인자로 받는 사용자 정의 생성자
public SuperTest108(String title)
{
this.title = title;
System.out.println("SuperTest108... 문자열을 인자로 받는 생성자");
}
public void write()
{
System.out.println(title + " - " + area);
}
}
// SuperTest108 클래스를 상속받는 자식 클래스
class Rect108 extends SuperTest108
{
/* 이거 두개 상속받은것!!
protected double area; // protected를 썻다!? -> 이거는 거의 상속을 염두해도 만들었다고 봐도 됨
public void write()
{
System.out.println(title + " - " + area);
}
*/
private int w, h; //w,h,area 가지고있는 변수 위에 상속까지
//자식 클래스의 사용자 정의 생성자
public Rect108()
{
// 자동으로 삽입
//super(); //== SuperTest108();
//super는 내가 속해있는 클래스 Rect108의 상속인 SuperTest108
}
public void calc(int w, int h)
{
this.w = w;
this.h = h;
//area = (double)this.w * h;// 이러면 매개변수 h이고 this.있으면 위에 private의 h
area = (double)this.w * this.h; //여기서 area는 물려받은 area
//super.area = (double)this.w * this.h; //라고 해도됨
//this.area = (double)this.w * this.h; //내가 가진 area라고 해도됨
write();
}
@Override //-- 어노테이션(annotation) - metadata - JDK 1.5 이상부터 지원됨
public void write()
{
System.out.println("w : " + w + ", h : " + h);
System.out.println("사각형 - " + area);
}
// ※ 메소드 오버라이딩(Method Overriding)
// 상위 클래스(부모 클래스)를 상속받은 하위 클래스(자식 클래스)에서
// 상위 클래스에 정의된 메소드를 다시 정의하는 것으로(재정의)
// 객체 지향 프로그래밍의 특징인 다형성을 나타낸다.
// 재정의(Overriding)는 반드시 상속 관계에 있어야 하며,
// 메소드의 이름, 리던타입, 매개변수의 갯수나 타입이
// 완전히 일치해야 한다.
// 메소드 오버로딩은 가져가다 쓰는 것이고 메소드 오버라이딩은 가져다가 !덮어쓰는것!
}
// SuperTest108 클래스를 상속받는 자식 클래스
class Circle108 extends SuperTest108
{
/* 이거 두개 상속받은것!!
protected double area; // protected를 썻다!? -> 이거는 거의 상속을 염두해도 만들었다고 봐도 됨
public void write()
{
System.out.println(title + " - " + area);
}
*/
/*
// default생성자 -> 아래의 사용자 정의 생성자가 있기 때문에 생성자가 생기지 않음!!!
public Circle108()
{
}
*/
//자식 클래스의 문자열을 인자로 받는 사용자 정의 생성자
public Circle108(String title)
{ //super(); 가 자동으로 삽입되기 때문에 인자없는생성자가 호출되는데 밑에 써주면 문자열로 인자를받는 생성자 호출!
super(title);
}
public void calc(int r)
{
area = r * r * 3.141592;
write();
}
}
// main() 메소드를 포함하고 있는 외부의 다른 클래스
public class Test108
{
public static void main(String[] args)
{
Rect108 ob1 = new Rect108();
//--==>> SuperTest108... 인자 없는 생성자
//Circle108 ob2 = new Circle108();
//--==>> 에러 발생(컴파일 에러)
//-- 현재 Circle108 클래스에는
// 매개변수를 필요로 하는 사용자 정의 생성자가 만들어져 있으며
// 이로 인해 default 생성자가 자동으로 삽입되지 않은 상황.
ob1.calc(10,20);
//--==>>SuperTest108... 인자 없는 생성자
// W: 10, h : 20
// 사각형 - 200.0
Circle108 ob2 = new Circle108("원");
ob2.calc(11);
//--==>>SuperTest108... 문자열을 인자로 받는 생성자
// 원 - 380.132632
}
}
/*
다음과 같은 프로그램을 구현한다.
단, 상속의 개념을 적용하여 작성할 수 있도록 한다.
실행 예)
임의의 두 정수 입력(공백 구분) : 20 15
연산자 입력(+ - * /) : -
>> 20 - 15 = 5.00
계속하려면 아무 키나 누르세요...
*/
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
//super class
class Aclass
{
protected int x, y;
protected char op;
Aclass()
{
}
void write(double result)
{
System.out.printf(">> %d %c %d = %.2f%n", x,op,y,result);
}
}
// sub class -> Aclass 를 상속받는 클래스
class Bclass extends Aclass
{
/* 이렇게 상속받음
protected int x, y;
protected char op;
// 생성자는 상속안됨! 그러나 생성자가 만들어지지 않아도 이게 만들어짐
//Bclass()
//{
// super();
//}
//
void write(double result)
{
System.out.printf(">> %d %c %d = %.2f%n", x,op,y,result);
}
*/
// 입력
boolean input() throws IOException //원래는 void 해도됨 새로운 방법
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //원래는 Scanner 사용하는데 버퍼드로 문자열자르는거 해볼것!
System.out.print("임의의 두 정수 입력(공백 구분) : "); // : 20 15
String temp = br.readLine(); // "20 15"
String[] strArr = temp.split("\\s"); //구분자 -> 공백
// String[] strArr = {"20", "15"};
// ※ 문자열.split("구분자")
// ex) "10 20 30 40".split("\\s"); //원래 \s가 공백!
// -> {"10", "20", "30", "40"} 반환
if(strArr.length != 2)
return false;
//-- false를 반환하며 input()메소드 종료
// 이 조건을 수행할 경우....
// 이 코드의 아래에 수행해야 할 코드가 남아있더라도
// 결과값을 반환하며 메소드는 종료된다~!!
x = Integer.parseInt(strArr[0]);
y = Integer.parseInt(strArr[1]);
System.out.print("연산자 입력(+ - * /) : ");
op = (char)System.in.read();
/*
// 논리연산자 부정 &&
if(op != '+' && op != '-' && op != '*' && op != '/')
{
return false;
}
return true;
*/
// 논리연산자 || => true false 부분도 바꿔써야함!!ㄴ
if(op=='+' || op=='-' || op=='*' || op=='/')
{
return true; //-- check~!!
}
return false; //-- check~!!
}// end input()
double calc()
{
double result = 0;
switch(op)
{
case '+' : result = x + y; break;
case '-' : result = x - y; break;
case '*' : result = x * y; break;
case '/' : result = (double)x / y; break; //나누기는 결과가 실수니까 한쪽에 double 붙여주기!
}
return result;
}//end calc()
/* 내가 푼것...
private int x, y;
private char op;
private double result;
public void calc(char op)
{
if (op=='+')
{
result = x + y;
}
if (op=='-')
{
result = x - y;
}
if (op=='*')
{
result = x * y;
}
if (op=='/')
{
result = x / y;
}
}
@Override
void write(double result)
{
System.out.printf(">> %d %c %d = %.2f%n", x,op,y,result);
}
*/
}// end Bclass
// main() 메소드를 포함하는 외부의 다른 클래스
public class Test109
{
public static void main(String[] args) throws IOException
{
Bclass ob = new Bclass();
if (!ob.input())
{
System.out.println("Error...");
return; // 프로그램 종료
}
double result = ob.calc();
ob.write(result);
}//end main()
}//end class Test109
/*
임의의 두 정수 입력(공백 구분) : 20 15
연산자 입력(+ - * /) : +
>> 20 + 15 = 35.00
계속하려면 아무 키나 누르십시오 . . .
임의의 두 정수 입력(공백 구분) : 20 15
연산자 입력(+ - * /) : -
>> 20 - 15 = 5.00
계속하려면 아무 키나 누르십시오 . . .
임의의 두 정수 입력(공백 구분) : 20 15
연산자 입력(+ - * /) : *
>> 20 * 15 = 300.00
계속하려면 아무 키나 누르십시오 . . .
임의의 두 정수 입력(공백 구분) : 20 15
연산자 입력(+ - * /) : /
>> 20 / 15 = 1.33
계속하려면 아무 키나 누르십시오 . . .
*/
-> @Override
void 메소드(int n) throws IOException, A 불가능!!
----
// 부모 클래스(상위 클래스, super class)
class SuperTest110
{
private int a = 5;
protected int b = 10;
public int c = 20;
public void write()
{
System.out.println("Super...write() : " + a + " : " + b + " : " + c);
//System.out.println("Sub...print() : " + b + " : " + c);
}
}
// 자식 클래스(하위 클래스, sub class)
class SubTest110 extends SuperTest110
{
protected int b = 100;
public void print()
{
//System.out.println("Sub...print() : " + a + " : " + b + " : " + c);
//--==>> 에러 발생(컴파일 에러)
//-- 슈퍼 클래스에서 선언된 변수 a 에는 접근할 수 없다.
// -> private 변수이기 때문에....
System.out.println("1 Sub...print() : " + b + " : " + c);
System.out.println("2 Sub...print() : " + b);
System.out.println("3 Sub...print() : " + this.b);
System.out.println("4 Sub...print() : " + super.b);
//-- 변수 b는 접근 방법에 따라 다른 b로 접근 및 출력이 이루어진다.
// 슈퍼 클래스에서 선언된 b, 서브 클래스에서 선언된 b
System.out.println("5 Sub...print() : " + c);
System.out.println("6 Sub...print() : " + this.c);
System.out.println("7 Sub...print() : " + super.c);
//-- 변수 c 는 접근하는데 아무런 제약과 제한이 없다.
// 슈퍼 클래스에서 선언된 c
}
@Override
public void write()
{
//System.out.println("Sub...write() : " + a + " : " + b + " : " + c);
//-- 이러면 에러남
//-- 오버라이드하면 더이상 부모메소드가 아니고 내가 덮어쓰는 것!!
//--==>> 에러 발생(컴파일 에러)
//-- 슈퍼 클래스에서 선언된 변수 a 에는 접근할 수 없다.
// -> private 변수이기 때문에....
System.out.println("Override Sub...write() : " + b + " : " + c);
// a 를 빼줘야함!
}
}
public class Test110
{
public static void main(String[] args)
{
// 하위 클래스(SubTest110) 인스턴스 생성
SubTest110 ob = new SubTest110();
ob.print();
//--==>> Sub...print() : 100 : 20
ob.write();
//--==>> Sub...print() : 5 : 10 : 20
System.out.println("-------------------------------------------------구분선");
System.out.println(ob.b);
//--==>> 100
System.out.println(ob.b); //부모로부터 물려받은 객체(10)를 외부클래스에서도 불러올수있을까?
System.out.println(((SuperTest110)ob).b);
//--==>> 10
// ※슈퍼 부름※ (괄호 check~!!!)
((SuperTest110)ob).write();
//--==>> Override Sub...write() : 100 : 20
// ※ 메소드와 변수를 꼭~!!! 구분하여 정리할 것!!!!
}
}