본문 바로가기

신세계 국비과정/신세게 - Java 공부

3주차 배운점 느낀점 - 생성자, 오버로딩, this(), 접근제한자, 조별과제

728x90
반응형

 

 

3주차 첫 조별과제

 

기본 문법들을 배우고 클래스와 각각 관계에 대해 배웠다. 처음으로 작지만 조별과제를 주셨다. 문제를 풀기전에 클래스 다이어그램을 통해 구현할 기능들에 생각하는 시간을 가졌고, 어떤 메소드를 가지면 좋을지 팀원과 토론했다. 얘기하다보니 꼭 필요한 메소드들이 갖추어졌고 미흡하지만 어느정도 구색을 갖추어서 코드구현을 시작했다.

 

배운점

 

생성자
객체를 생성할 때 new 연산자를 사용하여 호출되는 부분
클래스의 객체가 생성될 때 마다 자동으로 호출되고 객체를 초기화하는 데 이용되는 특수한 유형의 메서드 생성자명은 클래스명과 같고 반환 유형이 없음

 

생성자 규칙
생성자명은 해당 클래스명과 동일해야 함
생성자는 abstract, final, static을 선언할 수 없음
접근제한자는 생성자의 접근을 제어하는 데 사용할 수 있음. 즉 다른 클래스가 생성자를 호출할 수 있음

 

기본 생성자(default constructor)
매개변수가 없는 생성자
클래스 내에 기본 생성자를 정의 하지 않아도 됨
클래스 내에 기본 생성자를 정의하지 않으면 컴파일러는 해당 클래스에 대한 기본생성자를 자동으로 생성함

 

heap에는 breed, color(메소드)만 존재

 

 

멤버변수 private으로 할 것

 

생성자 오버로딩
생성자 이름이 같지만 매개변수가 다른 여러 생성자를 정의하는 것
매개변수의 자료형 또는 개수에 따라 구분
매개변수의 자료형이나 개수가 다른 생성자가 여러 개 있으나 생성자에 반환 자료형이 없음

 

생성자에 기능 넣을 수 있다. 되도록이면 하지말 것

 

Object : 모든 클래스 다 담을 수 있다.

 

intanceof
객체가 어떤 클래스인지, 어떤 클래스를 상속받았는지 확인하는데 사용하는 연산자 이다.
true , false 반환함
참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 사용

 

intValue()
객체에서 int형 값을 뽑아내는 메소드

 

public class Add {
  private Object a; // 모든클래스타입 다 담을 수 있다.
  private Object b;
  private int integerResult;
  private double doubleResult;

public void adder(Integer number1, Integer number2){
    if((number1 instanceof Integer)&&(number2 instanceof Integer)){
      int result = number1.intValue() + number2.intValue();
      System.out.printf("\n%d",result);
    }
  }
public void adder(Double number1, Double number2){
  if((number1 instanceof Double)&&(number2 instanceof Double)){
      double result = number1.doubleValue() + number2.doubleValue();
      System.out.printf("\n %.2f",result);
    }
  }
public void adder(Integer number1, Double number2){
  if((number1 instanceof Integer)&&(number2 instanceof Double)){
      double result = (double)number1.intValue() + number2.doubleValue();
      System.out.printf("\n %.2f",result);
    }
  }

 

필드 Object 형으로 받아서, 매개변수에 따라 instanceof 를 통해 Double 및 Integer 를 확인해준다. 그 후 intValue(),

doubleValue()를 사용하여 Integer -> int , Double -> double형으로 바꿔준 후 연산한다.

 

this()

생성자 부르는 특수 메소드, 생성자끼리 호출
this를 이용한 생성자 체인

 

this() 생성자
동일한 클래스 내의 서로 다른 생성자에서 오버로딩된 또 다른 생성자 하나를 호출하는 데 사용

 

생성자 체인(constructor chaining)
동일한 클래스의 다른 생성자에서 하나의 생성자를 호출하는 프로세스로, 생성자는 다른 생성자에서만 호출할 수 있으므로 생성자 체인이 필요함
다른 생성자에서 생성자를 호출하기 위한 this()는 현재 객체를 참조하는 데 사용함

 

public class Chain {
  Chain() {
    this(10);
    System.out.println("기본 생성자 Chain() 호출");
  }
  Chain(int x) {
    this(5, 6);
    System.out.println("일반 생성자 Chain(int x) 호출");
    System.out.println("x의 값 : "+ x);
  }
  Chain(int x, int y) {
    System.out.println("일반 생성자 Chain(int x, int y) 호출");
    System.out.println("x와 Y 값 : "+ x +" "+ y);
  }
}

 

 

 


호출하고 복귀하고 호출하고 복귀하고

 

this() 다른예제:

 

public class MemberChain {
  String firstName;
  String country;
  int age;

  public MemberChain(){
    this("홍길순");
  }
  public MemberChain(String mName){
    this(mName, 20);
  }
  public MemberChain(String mName, int mAge){
    this(mName, mAge, "대한민국");
  }
  public MemberChain(String mName, int mAge, String mCountry){
    firstName = mName;
    age = mAge;
    country = mCountry;
  }
  void printInfo(){
    System.out.println("이름 : "+firstName);
    System.out.println("국적 : "+country);
    System.out.println("나이 : "+age);
  }
}

 

메인:

 

public static void main(String[] args) {
    MemberChain object = new MemberChain();
    object.printInfo();
  }

 

기본생성자로 생성해도 firstName, country, age 가 할당된다.

 

 

접근제한자

 

접근성을 설정하는 데 사용되는 키워드로 다른 클래스의 클래스, 생성자, 데이터 멤버,
메서드의 접근을 제한함
불필요한 세부 정보를 숨기고 최소한의 정보만으로 프로그램을 손쉽게 사용할 수 있도
록 하는 정보 은닉의 캡슐화를 위해 접근제한자를 사용함
아무것도 안적으면 default
불필요한 세부정보, 데이터 보안 효과를 위해 접근제한자 사용!

 

 

조별 과제


선생님이 조별로 도서 장바구니 프로그램의 1.2.4. 번을 구현해 보라고 하셨다.

 

 

코딩에 앞서 문제를 보고 클래스 다이어그램을 그리기 시작했다. 코드를 짜기 전에 이렇게 클래스를 설계해 본적이 없다. 클래스란 현실 세계를 추상화 한것이라는 생각으로 필요한 부분을 필드로 두고 , 각각 필요한 기능을 구체화 해서 하나씩 메소드를 정의했다. 그러니 각 필요한 필드와 기능을 먼저 정하고 나니 코드 구현이 더 쉬웠다.
책정보를 담을 Book클래스를 만들었고 고객 정보를 담을 Customer 클래스를 만들었다. 기본적인 이름, 가격 , 고객의 전화번호등의 필드를 만들었다.
문제를 보니 Book을 고를때 정보들이 먼저 주어지고 우리가 선택해야하므로 bookPrint와 book id를 가져올 getBookId()를 만들었다.
고객 정보를 프린트 하는 메소드와, 카트에 담은 Book리스트를 ArrayList로 담았다.

 

 

 

Book class

 

public class Book {
  private String bookId;
  private String BookName;
  private int bookPrice;
  private String bookAuthor;
  private String bookSubName;
  private String bookCategory;
  private String bookDate;

  public Book(String bookId, String bookName, int bookPrice, String bookAuthor, String bookSubName, String bookCategory, String bookDate) {
    this.bookId = bookId;
    BookName = bookName;
    this.bookPrice = bookPrice;
    this.bookAuthor = bookAuthor;
    this.bookSubName = bookSubName;
    this.bookCategory = bookCategory;
    this.bookDate = bookDate;
  }

  public void bookPrint (){
    System.out.print(bookId+" | "+BookName+" | "+bookPrice+" | "+bookAuthor+" | "+bookSubName+" | "+bookCategory+" | "+bookDate+" | \n");
  }

  public String getBookId() {
    return bookId;
  }
}

 

 

Customer class

 

package project;

import java.util.ArrayList;

public class Customer {
  private String customerName;
  private String customerTel;
  private ArrayList<Book> bookCart = new ArrayList<Book>();

  public ArrayList<Book> getBookCart() {
    return bookCart;
  }

  public void addBookCart(Book book){
    this.bookCart.add(book);
  }
  public void printCartList(){
    for (Book book: bookCart) {
      book.bookPrint();
    }
  }

  public void printCustomerInform(){
    System.out.println("이름: "+customerName);
    System.out.println("전화번호: "+customerTel);
  }

  public Customer(String customerName, String customerTel) {
    this.customerName = customerName;
    this.customerTel = customerTel;
  }
}

 

 

처음에 Customer class 필드에 ArrayList booCart; 라고만 선언 해줬었다. 클래스멤버로 ArrayList를 선언해준적이 처음이었는데 자꾸 booCart를 사용하지 않는다는 메시지가 떴다. 곰곰히 생각 후 선언한 변수가 사용되지 않았다는건 메모리가 할당 되지 않았다는것을 떠올렸고, new 연산자를 통해 new ArrayList() 어레이리스트 객체를 생성해준 후 사용이 가능하였다.

 

Order class (main)

 

public class Order {
  public static void main(String[] args) {

    Scanner sc = new Scanner(System.in);
    String name;
    String tel;
    ArrayList<Book> bookMall = new ArrayList<>(); // 이 쇼핑몰 책리스트
    int choice; // 메뉴 선택번호
    String inputId = ""; // 입력받는 책아이디
    String inputTF;   // 장바구니 추가하겠습니까? Y|N

    Book book1 = new Book("ISBN1234", "쉽게 배우는 JSP 웹 프로그래밍", 27000, "송미영", "단계별로 쇼핑몰을 구현하며 배우는 JSP 웹 프로그래밍", "IT전문서", "2018/10/06");
    Book book2 = new Book("ISBN1235", "안드로이드 프로그래밍", 33000, "우재남", "실습 단계별 명쾌한 멘토링!", "IT전문서", "2022/01/22");
    Book book3 = new Book("ISBN1236", "스크래치", 22000, "고광일", "컴퓨터 사고력 키우는 블록 코딩", "컴퓨터입문", "2019/06/10");

    bookMall.add(book1);
    bookMall.add(book2);
    bookMall.add(book3);


    System.out.print("당신의 이름을 입력하세요 : ");
    name = sc.nextLine();
    System.out.print("연락처를 입력하세요 : ");
    tel = sc.nextLine();

    Customer cus1 = new Customer(name, tel); // 고객생성
    System.out.println("******************************");
    System.out.println("\tWelcom to Shopping Mall");
    System.out.println("\tWelcom to Book Market");

    while (true) {
      System.out.println();
      System.out.println("******************************");
      System.out.println("1. 고객 정보 확인하기");
      System.out.println("2. 장바구니 상품 목록보기");
      System.out.println("4. 바구니에 항목 추가하기");
      System.out.println("8. 종료");
      System.out.println("******************************");
      System.out.print("\n메뉴 번호를 선택해주세요 ");
      choice = sc.nextInt();
      sc.nextLine();

      switch (choice) {
        case 1 -> {
          System.out.println("고객 정보확인");
          cus1.printCustomerInform(); // 고객 이름, 전화번호 출력
        }
        case 2 -> {
          System.out.println("장바구니 상품목록 보기");
          if (!cus1.getBookCart().isEmpty()) { // 장바구니가 비어있지 않으면 장바구니 리시트 출력
            cus1.printCartList();
          }
          else {
            System.out.println("장바구니 비었습니다.");
          }
        }
        case 4 -> {
          boolean bookIs = true;

          for (Book book : bookMall) { // 쇼핑몰 책리스트 출력
            book.bookPrint();
          }
          while (bookIs) { // false 나올때까지 반복
            System.out.print("장바구니에 추가할 도서의 ID를 입력하세요");
            inputId = sc.nextLine();

            for (Book book : bookMall) {
              if (inputId.equals(book.getBookId())) {
                bookIs = false;
                // 입력받은 book아이디랑 쇼핑몰 책 리스트에 같은이름이 있으면 이 if문에 들어오고 bookIs는 false가 되어서 for문 빠져나옴
              }
            }
            if(bookIs) { // 같은 이름이 없으면 true 니까 if 실행 그리고 while 반복
              System.out.println("목록에 그런 책이없습니다.");
            }
          }


          System.out.print("장바구니에 추가하시겟습니까? Y|N"); //
          inputTF = sc.nextLine();
          if (inputTF.equals("Y")) {
            for (Book book : bookMall) {
              if (book.getBookId().equals(inputId)) {
                cus1.addBookCart(book); // Y면 장바구니에 추가
                System.out.println(book.getBookId() + " 도서가 장바구니에 추가되었습니다.");
              }
            }

          } else if (inputTF.equals("N")) {
            System.out.println("N입력");
          } else {
            System.out.println("다시해라 YN중에 해주세요");
          }
        }
        case 8 -> {
          System.out.println("종료");
          System.exit(0);
        }
        default -> {
          System.out.println("1부터 8까지 중에 입력하세요.");
        }
      }
    }
  }

 

메뉴 번호 선택을 위해 choice라는 int값을 받았고 그 뒤 book id를 Scanner를 통해 입력받았는데 자꾸 bookid입력을 건너 뛰는 것이었다. 한강형님이 검색해 보니 int형을 sc.nextInt()로 입력 받은 후 '엔터'값이 아직 남아있어 다음 nextLine()메소드에 입력이 되어 그냥 넘어가짐을 알았다.

 

기본적인 기능을 구현하고 예외처리에대해 생각했다. 사용자가 입력할 수 있는 모든 경우의 수에 대비해야한다. 나혼자였다면 else 문으로 다시입력하라는 간단한 예외밖에 생각나지 않았을 것이다. 팀원과 머리를 맞대니
"장바구니에 추가하시겠습니까? Y|N"에서 "N"입력의 경우, 그 외의 입력인 경우 ,
메뉴 번호 선택시 1~8 중 다른것을 입력했을 경우, 도서 아이디를 잘못입력햇을때 잘못 입력했다는 메시지와 다시 입력으로 돌아가는 반복문 등 , 다양한 경우의 수를 떠올릴 수 있었다.
입력을 받을때, 각각 입력되는 경우, 그 외의 경우, 잘못입력했을 경우, 제대로 입력했을 경우, 잘못입력하였을 때 다시 입력할 수 있도록 되돌아가는 경우를 떠올릴 수 있음을 배웠다.

 

피드백

 

로직을 잘 짰다.
대신 결합하는 부분에서 정리만 잘하면 될 것 같다. (예 : 퍼져있는 ArrayList 줄이기)
배운내용에 충실히 짰다고 해주셨다. 다른 조들을 보니 클래스들이 많았다. 우리조도 리펙토링을 통해 결합도를 낮출 필요가 있다고 생각했다.

반응형