KOSTA 6일차) mvc / toString / 클래스 / 오버로딩

해버니·2023년 2월 21일
0

KOSTA

목록 보기
13/32
post-thumbnail

toString()

객체 설명 메서드, 객체의 중요 정보를 하나의 문자열로 엮어서 반환


❓ 어떤 정보가 중요한 정보일까 ❓
① 이 객체의 클래스 타입
② 힙에 할당받은 메모리 주소




자바에서 사용하는 모든 클래스는 오브젝트라는 클래스가 있고 상속을 받는다.
object class는 toString이라는 메소드를 가지고 있다.

package addr;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Member m1 = new Member("min", "010-1111-1111", "대한민국");
		Member m2 = new Member("hyun", "010-2222-2222", "한국");

		System.out.println(m1.toString());
		System.out.println(m1); // addr.Member@6f2b958e
		System.out.println(m2); // addr.Member@5e91993f
	}
}

toString()을 써보면 패키지명.클래스명@참조값 이 나오는 것을 알 수 있다.

그리고 주소값도 중요하지만 내가 원하는 값이 들어갔는지 확인 하는 것도 중요하다.
오늘 멤버변수값을 확인하려고 print()를 만들어서 확인을 했었는데
이와 유사한 형태로 toString을 가지고 원하는 값이 들어가 있는지 확인할 수 있다.








복습

객체지향 : 프로그래밍 하는 방법이다.

객체지향은 개념을 이해하고 정해진 문법(?)에 맞춰서 잘 짜는게 중요하다.
예를 들어 제어문은 내가 짠 코드가 정삭적으로 돌아간다면 그게 정답이지만 객체지향은 정상적으로 돌아간다고 하더라도 본인의 코드가 무조건 정답이라고 말할 수는 없다.

객체 프로그래밍을 하는 이유는 여러 사람들과 같이 협업하기 위해서이다.
그러려면 프로그래밍 패턴이 맞아야 하고 객체 지향으로 코드를 짜는 연습을 많이 해봐야 한다.



new는 힙에 메모리 할당하기 위해서 존재한다.
메모리 초기화해주는 친구가 누구? 생성자!
생성자 특징은 클래스와 이름이 같다.
클래스 안에 있는 친구를 메소드라고 한다.





자바는 두 개의 관계가 있다.


① "포함" account 포함 관계
다른 클래스를 멤버변수로 갖는 것

② "상속"
상속을 담으면 부모의 것을 고대로 물려받는다.








MVC

① m : model
② v : view
③ c : controll

model : VO, DAO, SERVICE
view : UI
c : 데이터 흐름 제어 (servlet 등)








mvc에서 사용하는 클래스들의 종류 (VO, DAO, SERVICE)


① VO(value object)

한 객체의 정보를 묶어서 한 변수에 담는 용도 → 캡슐화

주고받는 데이터 객체의 구조를 결정한다.
계층간 데이터 교환을 위해 사용하는 객체이다.

예를 들어 카드의 정보를 담고 싶다 → 카드사/카드번호/비밀번호 등등
이러한 클래스를 VO(value object)라고 한다.

DTO와 유사 Data Transfer Object : '데이터를 교환하는 객체'
단, VO는 read-onlt라는 점에서 DTO와 다르다.





② DAO (Database Access Object)
배열에 데이터 저장, 검색, 수정, 삭제 (저장소가 기준)
데이터에 접근하는 객체 SELECT, INSERT, UPDATE, DELETE 등 데이터 처리가 주 목적





③ SERVICE →사용자
비즈니스 로직 제공 : 사용자
사용자에게 제공할 기능을 구현하는 것
기능은 메소드로 구현한다.




❓ Service와 DAO의 차이 ❓
단순하게 페이지를 불러오고 DB정보를 한번에 불러오는 간단한 프로젝트의 경우 Service와 dao의 차이가 거의 없을 수 있다.

사용자가 한 번의 요청으로 단순히 페이지 이동이 필요하다면 select와 같은 단순히 하나의 dao만 작동하기 때문에 Service와 dao가 나눌 필요가 없는 것처럼 보이지만,

사용자가 글을 작성하거나 수정하는 것과 동시에 페이지가 이동한다면 update, select가 작동하기 때문에 여러 dao를 Service안에 조립하는 로직을 갖게된다.










클래스

한 객체의 정보를 묶어서 한 변수에 담도록 타입을 정의
멤버변수메서드로 구성되어 있다.



클래스 만들 때

① 기능정의
어떤 기능을 제공할지 정해야 한다.
② 기능명세
순서같은거 말하는 건가
카드를 넣는다 → 비밀번호를 입력한다 → 등등등
③ 객체도출
④ 객체를 클래스로 정의





class 클래스명 {
멤버변수 정의;
}


// 타입명 : Test
// Test 타입의 변수는 int값 1개, String 1개를 묶어서 저장

class Test{
   int a;
   String b;

   // 반환타입을 뭘로하면 좋을까?
   // setter : 파람으로 받은 값을 멤버변수에 할당.
   // setter는 항상 메서드 타입이 void이다. 
   // 할당만하지 값을 반환할 필요가 없다.
   
   void setData(int x, String y){
      a = x;
      b = y;
      // 값 할당을 대신하기 위해서 만들기 위함이다. 
   }

   void printData(){ 
      System.out.println("a : " + a + "b : " + b) ; 
   }
}



// 객체 생성 → 메모리 할당
Test t1= new Test();

// . → 멤버 변수 접근 연산자 
t1.a =10;
t1.b ="zzanggoo"

Test t1 = new Test();
t1.setData(1234, "love");
t1.printData();

Test[] arr = new Test[2];
arr[0] = new Test();
arr[0].a = 30;
arr[0].b = "hi";
arr[0].setData(30, "hi");

arr[1] = new Test();
arr[1].setData(11, "Zzz");

for(int i = 0; i < arr.length; i++){
   arr[i].print();
}



💡 어떤 분이 소스가 제대로 안 돌아가서 확인 후 알려주신 부분 💡
멤버변수는 자동으로 초기화가 되는데 지역변수는 자동으로 초기화 되지 않는다.
그래서 안전성때문에 지역변수는 초기화하고 사용하는 것이 바람직하다.











생성자

객체 초기화 메서드


이름은 클래스와 동일하고 반환타입은 없다.

우리가 생성자를 만들지 않더라도 컴파일러가 자동으로 생성해준다.
하지만 생성자를 하나라도 작성하면 자동생성 안 됨
생성자는 마음대로 호출할 수 없고 객체 생성시에만 호출가능
파라미터는 있을 수도 있고 없을 수도 있지만 동일하게 해서 호출을 해야 한다.



class Member2 {
	String name;
	String tel;
	String addr;

	// 생성자 : 객체 생성할 때. 그 외에는 호출할 수 없다.
	// 멤버 변수를 초기화하려는 목적으로 사용한다.
	Member2() {
		System.out.println("생성자");
		name = "hyun";
		tel = "010-1111-1111";
		addr = "대한민국";
	}

	void print() {
		System.out.println("name : " + name);
		System.out.println("tel : " + tel);
		System.out.println("addr : " + addr);
	}
}

public class ComstructorTest {

	public static void main(String[] args) {
		Member2 m = new Member2();
		m.print();
		// 생성자
		// name : hyun
		// tel : 010-1111-1111
		// addr : 대한민국
		
		m.name = "min";
		m.tel = "010-2222-2222";
		m.addr = "제주도";
		m.print();
		// name : min
		// tel : 010-2222-2222
		// addr : 제주도
	}

}






💡 생성자는 기본적으로 만들어주는 것이 좋다 💡

내가 생성자를 작성하면 디폴트 생성자가 제공이 안된다.(?)
그래서 나중에 쓸 때 에러가 날 수 있어서 디폴트 생성자는 습관적으로 해주는 것이 좋다.
Member3(){} 이런식으로 생성해주면 된다.


class Member3 {
	String name;
	String tel;
	String addr;

	Member3() {
	}

	Member3(String n) {
		name = n;
	}
}








메서드 오버로딩 (오버로딩) (Method Overloading)

동일한 이름의 메서드 여러개를 만들 수 있다.
단, 파라미터의 개수나 타입을 다르게 해줘야 함.
리턴타입과는 상관 없다.


이게 필요할까?
값을 넣어서 만들 때도 있지만 파라미터가 하나도 없는 것이 필요할 때도 있기 때문에.



package prj2_3;

class Member3 {
	String name;
	String tel;
	String addr;

	Member3(String n, String t, String a) { // 메서드 오버로딩
		System.out.println("생성자");
		name = n;
		tel = t;
		addr = a;
	}
 
	Member3() { // 메서드 오버로딩 : 디폴트 생성자
		System.out.println("생성자");
		name = "min";
		tel = "010-1111-1111";
		addr = "한국";
	}

	void print() {
		System.out.println("name : " + name);
		System.out.println("tel : " + tel);
		System.out.println("addr : " + addr);
	}
}

public class ConstructorTest2 {

	public static void main(String[] args) {

		Member3 m = new Member3("hyun", "010-1111-1111", "대한민국");
		m.name = "min";
		m.tel = "010-3333-4444";
		m.addr = "한국";
		m.print();
		
		Member3 m2 = new Member3();
		m2.print();
		// name : min
		// tel : 010-1111-1111
		// addr : 한국
	}

}




int, String, float 더하기


메소드 오버로딩이 없었다면

int add_int(int a, int b){
	return a + b;
}
String add_String(String a, String b){
	return a + b;
}
float add_float(float a, float b){
	return a+b;
}

add_int(1, 4);
add_String("aaa", "bbb");
add_float(2.3f, 5.6f);




메소드 오버로딩

int add(int a, int b){
	return a + b;
}
String add(String a, String b){
	return a + b;
}
float add(float a, float b){
	return a+b;
}

add(1, 4);
add("aaa", "bbb");
add(2.3f, 5.6f);

이렇게 간단하게 만들 수 있다.



package prj2_3;

public class OverTest {
	int add(int a, int b) {
		System.out.println("add int : " + (a + b));
		return a + b;
	}

	String add(String a, String b) {
		System.out.println("add String : " + (a + b));
		return a + b;
	}

	float add(float a, float b) {
		System.out.println("add float : " + (a + b));
		return a + b;
	}

	public static void main(String[] args) {
		OverTest o = new OverTest();

		o.add(1, 2);
		o.add("min", "hyun");
		o.add(3.14f, 3.14f);

	}

}









this

현재 객체의 참조값을 갖는 참조변수
멤버 변수와 지역 변수 이름이 같을 때 멤버 변수를 구분하기 위해서
사용을 한다.
(이름 만들려면 귀찮기 때문에)
(코드의 흐름은 지역변수에서 먼저 찾고 그다음에 멤버변수에서 찾는다.)

this.name=name;		//  이렇게 쓰지 않고
this				//	이렇게 딱 하나만 써도 되는데 
					//  이 뜻은 현재 객체의 참조값이 할당되는 것이다.










static

정적(static) 멤버 정의

저장되는 메모리가 다르면 특성도 다르다.
언제 시작되고 언제 끝나는지, 유효시간 범위나, 자동으로 초기화가 되는지 등등 이런 특징이 결정되는 것이다.


class Test{
   int a;			// 일반 멤버 변수. 객체 소속
					// 객체마다 따로 사용 
					// 언제 만들어져 ? 객체 생성시
					// 일반 멤버변수는 객체를 생성해야 존재 
   static int b;	// static 변수. 클래스 소속
					// 모든 객체가 공용으로 사용
					// 언제 만들어져 ? 프로그램 시작시 만들어짐
					// 이 말은 객체를 만들지 않아도 만들 수 있는 것과 같다.
					// 얘도 자동으로 0으로 초기화
					// static 멤버는 객체 유무와 상관없이 존재
}

Test t1 = new Test();
Test t2 = new Test();
Test t3 = new Test();
// a 3개만 heap에 할당이 된다. 
// static 멤버는 b 한 개만 할당이 된다. 

t1.a = 1;
t2.a = 2;
t3.a = 3;
Test.b = 100;





static 메서드
클래스 소속이기 때문에 "클래스.메서드()"로 호출함
객체 생성없이 사용 가능


주의사항
일반메서드에서는 static 멤버변수 사용이 가능하지만 static 메서드에서 일반 멤버변수는 사용불가
일반메서드에서 static 메서드 호출은 가능하지만 static 메서드에서 일반 메서드 호출은 불가능

왜그럴까?
일반 메소드는 객체가 생성돼야 객체호출이 가능하지만
static 멤버 변수는 객체가 생성되기 이전에 존재하게 되기 때문이다.
(프로그램이 시작할 때부터)









참고
https://ysyapr91.tistory.com/4
https://webstudynote.tistory.com/103

0개의 댓글