Java 6일차 : 클래스
클래스
- 클래스는 설계도면 같은것
-
필요한 요소들을 넣어서 설계를 하고 그 설계대로 집을 짓는다
- 마찬가지로 클래스구조를 설계해서 만든다음, New로 인스턴스 생성을 하면 비로소 메모리에 클래스 객체가 생성되며, 이것이 집의 주소와 같은 개념이라고 보면된다.
공부해야할것
- 멤버 변수, 멤버 메소드 구현하는 방법
- 접근 지정자
- 클래스 객체를 생성 후 메소드 호출하는 방법
- 오버라이드 메소드에 대한 이해
- 생성자
- 상속
- 다형성
package test.day0410;
public class ObjectEx2 {
//멤버 변수 선언하는 위치 - 이안에서 생성될 오브젝트에서 공통적으로 사용할 수 있는 변수
//형식 : 접근지정자 [final, static] 데이타타입 변수
//접근지정자(4개) : public, protected, private, 생략
//public : 모든 패키지에서 접근 가능
//private : 타 패키지 뿐 아니라 같은 패키지에서도 접근 불가능. 현재 클래스 멤버만 접근 가능
//protected : 패키지가 다를 경우 상속관계의 클래스만 접근을 허용하고 싶을 때
//생략시 : 다른 패키지에서 무조건 접근 불가
private int x1 = 100;
private String msg="happy";
public void writeMember() {
System.out.println(x1); //멤버메소드에서는 멤버변수 바로 접근 가능
System.out.println(this.x1); //this라는 인스턴스 변수가 기본적으로 존재(위처럼 생략 가능)
System.out.println(msg);
System.out.println(this.msg);
}
//멤버 메소드라 하더라도 static메소드는 this를 갖고있지 않다.
public static void main(String []arg) {
// System.out.println(x1); //메인에서는 같은 클래스라 하더라도 new로 생성 후 호출해줘야함
//현재 클래스에 대한 객체 생성
ObjectEx2 ex = new ObjectEx2();
//이제 멤버변수를 호출할 수 있다.
System.out.println(ex.x1 + 1);
System.out.println(ex.msg + " main method");
//멤버 메소드 호출
ex.writeMember();
}
}
package test.day0410;
import test.day0409.Apple2;
public class ObjectEx3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//같은 패키지의 apple멤버 메소드를 호출하자
Apple apple = new Apple();
apple.testPublic();
apple.testProtected();
apple.testDefault();
//apple.testPrivate(); -> 오류
//같은 패키지내에서는 private을 제외한 접근지정자는 모두 접근가능
Apple2 apple2 = new Apple2();
apple2.testPublic();
//다른 패키지에 있는 클래스는 퍼블릭 메소드만 접근 가능
}
}
package test.day0410;
class Orange{
int n = 10;
public void test1() {
int n = 20;
//같은 이름의 지역변수가 없다면 멤버변수가 출력되지만
//같은 이름의 지역변수가 있다면 지역변수가 우선으로 출력
System.out.println(n);
//만약 멤버변수를 호출해주고 싶다면 반드시 this.n으로 사용!
System.out.println(this.n);
}
public void test2(int n) {
System.out.println(n);
System.out.println(this.n);
}
}
class Kiwi{
//static 멤버변수는 외부에서 클래스명. 상수명 으로 접근 가능
public static final String MSG = "Happy Day!!!";
public static final double PI = 3.141592;
}
public class ObjectEx4 {
public static void main(String []arg) {
Orange or = new Orange();
or.test1();
or.test2(5);
//static 변수나 메소드는 모든 객체에서 공동으로 사용할 목적으로 만들어짐
//new로 굳이 객체생성 불필요함
System.out.println(Kiwi.MSG + Kiwi.PI);
}
}
package test.day0410;
class Berry{
private static String msg = "Happy";
private String addr = "Seoul";
public void test1() {
System.out.println(msg);
System.out.println(addr);
}
public static void test2() {
System.out.println(msg);
//System.out.println(addr); //static메소드안에 non-static 변수를 사용x
//굳이 non-static 변수를 쓰고 싶으면 항상 아래처럼 호출 후 사용해줄
Berry br = new Berry();
System.out.println(br.addr);
}
public void hello1() {
test1();
test2();
}
public static void hello2() {
//test1(); //static 메소드 안에 non-static 메소드를 사용x
test2();
}
}
public class ObjectStaticEx5 {
public static void main(String[] args) {
}
}
기본적으로 class는 인스턴스가 생성되기 전까지는 단순히 설계도에 불과한 것처럼 보인다.
다만, 클래스 내의 static 변수나 static 메서드는 이미 그 선언 자체로 사용이 가능하다.
그러니까 여러개의 집을 짓기 전에 설계도를 작성하지만, 어쨋든 지어질 집이라면 단지 내 주차장은 어차피 만들어야하니, 귀찮게 집을 지을때마다 주차장을 만들지 말고 걍 미리 주차장은 만들어놓는다는 개념
같은 원리로 공동의 어떤 행동을 할 때, 공동의 것이 아닌 변수를 가져오는것은 불가능(왜냐하면 설계도가 존재한다는 것 자체로 101호가 존재한다고 볼 순 없기 때문임)
그래서 non-static 변수를 가져오기 전엔 반드시 집(인스턴스)을 적어도 하나는 짓고 가져와야함
같은 원리로 공동의 어떤 행동을 할 때, 공동의 것이 아닌 행동을 가져오는것은 불가능
마찬가지로 그냥 설계도만 있는 상태이기 때문에 101호 청소하기 같은 non-static 메소드를 공동계단 청소하기같은 static 메소드에 집어넣는것은 안됨 (101호가 없는데 어떻게 청소를해?)
실습문제
Student 라는 클래스를 설계해보자
멤버변수(모두 private) : 이름 name / 주소 addr / 반 room - static / 점수 score
멤버메소드 : setName / setAddr / setRoom - static / setScore / writeStudent - 전체 데이타 출력하는 메소드
package test.day0410;
class Student {
//멤버 변수 선언
private String name;
private String addr;
static int room;
private int score;
//setter멤버메소드
public void setName(String name) {
//전달받은 인자 name을 멤버변수에 넣기
this.name = name;
}
public void setAddr(String addr) {
this.addr = addr;
}
public static void setRoom(int room) {
Student.room = room;
}
public void setScore(int score) {
this.score = score;
}
public void writeStudent() {
//같은 멤버끼리는 this나 Student 생략가능
System.out.println("name: " + name);
System.out.println("addr: " + addr);
System.out.println("room: " + room);
System.out.println("score: " + score);
}
public void setStudent(String name, String addr, int score) {
setName(name);
setAddr(addr);
setScore(score);
}
}
public class StudentEx6 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student alice = new Student();
Student bob = new Student();
alice.setName("alice");
alice.setAddr("Seoul");
alice.setRoom(3); //어차피 이건 공유되는거니까 그냥 Student.setRoom으로 줘도 된다.
alice.setScore(90);
alice.writeStudent();
System.out.println();
bob.writeStudent(); //room 변수는 이미 들어가 있다.
System.out.println();
bob.setName("bob");
bob.setAddr("Busan");
bob.setScore(13);
bob.writeStudent();
System.out.println();
alice.setStudent("chris", "Seattle", 88);
alice.writeStudent();
}
}
의문점
static 메서드에서, 해당 클래스의 인스턴스 변수에 접근하기 위해 생성된 오브젝트 obj가 있다고 하자. 이 때 메인메서드에서 이 오브젝트에 접근할 수 있는가? 예를들어 obj.var1 값을 메인메서드에서 호출할 수 있는가?
=> 된다. 만약 그 static메서드가 obj를 반환하도록 되어있다면.
그럼 메인메서드에서 그 static메서드를 호출하면, obj를 얻을 수 있으므로 자유롭게 변수에 접근 가능하다. 근데.. 음….. 변경도 가능한가? call-by-value인가?
=> call-by-value다. 변경은 안된다. 변경값을 저장하고 싶다면 애초에 메인메서드에서 obj를 다른 인스턴스에 저장해서 사용해야 변경이 유효하다.
Return 타입
package test.day0410;
class Banana{
private String name = "Lisa";
private int age = 17;
public int myAge() {
return age;
}
public String myName() {
return name;
}
public Banana getBanana() {
return this; //현재값으로 반환(나이,이름)
}
public static Banana getMyData() {
Banana b = new Banana();
b.name = "Rose";
b.age = 20;
return b;
}
}
public class ReturnTypeEx7 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Banana bn = new Banana();
System.out.println(bn.myAge() + bn.myName());
System.out.println(bn.getBanana().myAge()); //메서드 직접 호출
Banana b2 = Banana.getMyData(); //static 메서드 호출
//위에서 getMyData는 banana 클래스의 오브젝트를 반환하므로 b2에 저장될 수 있다
System.out.println(b2.myName());
}
}
package test.day0410;
class MyMath{
public static double sum(double a, double b) {
return a+b;
}
//overloading method(중복 메서드) - 메서드 명은 같으나 인자는 서로 달라야함
public static double sum(double a, double b, double c) {
return a+b+c;
}
//...배열타입
public static double sum(double...d) {
double s = 0.0;
for(int i = 0 ; i<d.length ; i++) {
s += d[i];
}
return s;
}
}
public class ReturnTypeEx8 {
public static void main(String[] args) {
// TODO Auto-generated method stub
double d1=MyMath.sum(3.2, 5.1);
System.out.println(d1);
System.out.println(MyMath.sum(1.1, 2.2, 3.3)); //오버로딩
System.out.println(MyMath.sum(1.1,2.2,3.3,4.4,5.5));
}
}
Variable Arguments
- 같은 타입으로 여러개의 값을 인자로 받을 경우, 여러개의 오버로딩 메서드를 만들어야 하는 경우에 유용하게 쓸 수 있는 기능이다 (jdk5.0에서 추가)
package test.day0410;
public class VaragesEx9 {
//variable argument ...
public static void writeString(String...str) {
System.out.println(str.length + "개의 문자열 받음.");
for(int i = 0 ; i < str.length ; i++) {
System.out.print(str[i]);
}
}
public static void main(String []arg) {
writeString("안녕하세요~!!", "ㅎㅇㅎㅇ","ㅎㅎ");
}
}
실습문제
다음과 같은 클래스를 구현하시오
클래스명: Pay
멤버변수 : gibon : 기본급, sudang : 수당, tax : 세금
=>모든 멤버변수는 private 으로 주고 setter & getter 메소드를 구현한다
=>메소드 추가 calcTax : 기본급의 3프로를 tax 에 지정한다
클래스명 : Sawon
멤버변수 : name : 사원명, mypay : 급여에 대한 정보
멤버 메소드 :
initPay :기본급과 수당을 전달받아서 mypay 에 전달,
writeSawon : 사원명,기본급,수당,세금 출력하는 메소드
package test.day0410;
class Pay{
private int gibon, sudang, tax;
public int getGibon() {
return gibon;
}
public void setGibon(int gibon) {
this.gibon = gibon;
}
public int getSudang() {
return sudang;
}
public void setSudang(int sudang) {
this.sudang = sudang;
}
public int getTax() {
return tax;
}
public void setTax(int tax) {
this.tax = tax;
}
public void calcTax() {
this.tax = (int)(gibon*0.03);
}
}
class Sawon{
String name = "홍길동";
Pay myPay = new Pay();
public void initPay(int gibon, int sudang) {
myPay.setGibon(gibon);
myPay.setSudang(sudang);
}
public void writeSawon() {
System.out.println(name);
System.out.println(myPay.getGibon());
System.out.println(myPay.getSudang());
System.out.println(myPay.getTax());
}
}
public class ClassTestEx11 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Sawon sa=new Sawon();
sa.initPay(1260000,350000);
sa.myPay.calcTax();
sa.writeSawon();
}
}
Comments