Java

20.07.02 Java_ScoreV2 클래스 상속, 향상된 for문, 인터페이스, Implements,유효성 체크, 객체지향프로그램의 특징

우롱차 2020. 9. 2. 20:19
728x90
Java Doit
p. 313 < 인터페이스
p.327  인터페이스 상수  < 최신 버전만
< 기본인터페이스에는 없다라고 보면 됌

 


다시 리스트에 추가했기 때문에 다시 size 재정의
항상 size 값을 어떤 변수에 담고 for문을 반복해야함
위에서 add가 될수도 있고 빠질수도 있어서
내가 그 size를 모르니까!
int size = strList.size();
for(int i = 0 ; i < size ; i++) {
String str = strList.get(i);
System.out.println(str);
}
strList.add("이몽룡");
 
size = strList.size();
// size를 한번만 조회를 하면 알아볼 수 있는데
// 얘는 for문이 반복되는 동안 size() method가 계속 반복이돼서
// 위의 코드와 다르게 상당히 비효율적이다.
// 그래서 우리는 size를 먼저 알아보고 for문을 반복하자!
 
* for 문이 strList개수만큼 반복 수행되는 동안
* 계속해서 size() method를 호출하여 연산을 수행하도록 한다.
* strList 개수가 for 반북몬 내에서 변경되지 않는 경우
* 매우 불필요한 연산 반복 수행하는 결과가 된다.
for( int i = 0 ; i < strList.size() ; i++) {
// 위 코드와는 다르게 한줄로 줄여서 출력할 수 있음
System.out.println(strList.get(i));
}
 
// 개수를 1번만 조회하고 for 반복문 수행하기
// 이 코드는 개수를 1번만 조회하고 for 반복문을 수행하기 때문에
// 위의 코드보다는 효율적이다 
// 하지만 개수를 조회하는 코드를 생략하면 혹시 리스트 개수가 변경되었을 때
// for 반복문 연산 수행에 문제가 될 수 있다.
size = strList.size();
for( int i = 0 ; i < size ; i++) {
System.out.println(strList.get(i));
}

향상된 for문

// List 전체에 대해서 for 반복문을 수행할 경우
// 사용할 수 있는 향상된 for, forEach문 라고 한다.
// 1. strList 개수만큼 알아서 for가 반복된다.
// 2. for가 반복되면서 strList.get(현재)를 str 변수에 할당
// 3. for 반복문 내에서 str 변수 값을 읽어서 사용할 수 있다. >> 이러면 사이즈 조회도 할 필요 없이 사용할 수 있다.
// >> 알아서 컴파일이 바로 위코드로 변환이 되서 우리가 이렇게만 적어줘도 알아서 
for(String str : strList) {
System.out.println(str);
}
// 배열도 향상된 for를 사용하여 반복문을 수행할 수 있다.
int[] intArray = new int[100]; // intArray는 0~99까지 100개가진 배열
    for(int i : intArray) {
System.out.println(i);
}
>>>>>>>> score > ListEx_01🙂

인터페이스

ScoreService 클래스를 디자인하기
  • boolean inputScore()
  • void calcSum()
  • void calcAvg()
  • void  scoreList()
 
  • 인터페이스
    • 자바 클래스의 한 형태이다.
    • 메서드들의 원형(Prototype)을 정의만 할 수 있다.
    • 메서드들이 할일(코드)는 구체적으로 작성할 수 없다.
    • 모든 메서드는 {} 없이 메서드에서 바로 문장이 종료된다.
    • 인터페이스를 implements할 클래스에 규칙을 지정한다.
 
  • 인터페이스를 implements한 클래스는
    • 인터페이스에 정의된 모든 메서드를 구현해야한다.
    • 인터페이스에 정의된 모든 메서드들을 의무적으로 포함해야한다.
    • 인터페이스에 정의된 메서드 이름을 변경하여 사용할 수 없다.
    • 자신이 어떤 메서드를 구체적으로 만들어야하는지 명확히 할 수 있다.
 
  • 인터페이스를 implements한 클래스를 사용하는 곳에서는
    • 지금 호출하는 method는 어떤 클래스를 사용하든 같은 이름일 것이다. 라는 기대
    • 지금 호출하는 method가 반드시 존재하는 메서드이다. 라는 기대
    • 혹시 다른 클래스를 사용해서 객체(인스턴스)를 생성했을 때
    • 나머지 부분의 코드를 (거의) 변경없이 테스트, 사용이 가능하다는 기대
 
★★★★★★★★★★ 중요 ★★★★★★★★★
인터페이스를 사용하므로 해서 (Service) 클래스와 (Main) 클래스 간에 <보통 모듈과 모듈이라 함>
결합도는 낮아지고 응집도는 높아져서 개발생산성, 유지보수성, 등이 매우 좋아진다.
인터페이스를 잘 디자인 해두면, 어플리케이션을 만들어가는 과정 중에 후반부로 갈수록 시간, 비용 등이 절약된다.
 
public interface ScoreService {
    public boolean inputScore(); // method() { .... }
    public void calcSum();
    public void calcAvg();
    public void scoreList();
}
>>>>>>>> service > ScoreService🙂

 


Implements

  • ScoreService*** 클래스를 정의할 때
  • 반드시 ScoreService interface를 참조(implements)하도록 규칙을 정해 놓는다.
  • ScoreService interface를 참조하는 클래스는 ScoreService interface에 디자인된 method를 모두 implement해서 작성되어야 하는 규칙이 작동하게 된다.
  • 따라서 모든 method의 이름이 통일되는 효과를 얻게 된다.
 
  • interface(ScoreService)를 implements하여 작성된 클래스는
  • interface에 정의된 method의 규칙을 그대로 준수하여 작성해야할 의무가 있는 클래스다.
  • 모양은 interface의 모양을 그대로 가지고 있으며
  • 하는일은 실제 클래스의 method에 구현되어 있다.
// private 되어있던 필드변수를 protected로 변경
protected List<ScoreVO> scoreList;
protected Scanner scan;
 
* sVO.setSum() method에 총점을 전달하므로써
* scoreList에 저장된 어떤 요소의 총점 변수에 값을 저장하는 효과를 낸다.
* 별도로 저장을 해주거나 하는 절차가 필요없다.
 
sVO.setSum(intSum);
// add를 안해준 이유는 sVO가 i를 가르키는 주소임!
// get을 가지고와서 sVO에 저장해주고 sVO.set만 해주면 자동으로 intSum이 추가가 되더라
>>>>>>>> service > ScoreServiceImplV1🙂

클래스를 상속

  • extends : 확장하다
  • = inherit : 상속받다
 
  • 자바에서 클래스 상속
  • 자바 객체지향 개념에서 가장 중요한 개념으로
  • 기존에 잘 만들어진 클래스를 상속받아(inherit)
  • 그 중 일부 method를 나만의 코드로 바꾸어서 사용하고 싶을 때
  • 클래스를 확장하여(extends)참조하고
  • 필요한 method를 재정의(override)하여 사용한다.
//스코어 implv1에 있는 모든 코드가 v2가 이어받아서 사용하겠다는의미.
// v1에 있는 코드가 v2에 전부 복붙이기가 되어있다!
// extends하나로 v1에있는 코드가 변경이되어도 v2는 그대로 갖다쓰기때문에 코드가 변경되도 별 상관이 없다.
public class ScoreServiceImplV2 extends ScoreServiceImplV1 {
  • ScoreServiceImplV2에는 보이지는 않지만 ScoreServiceV1의
  • 모든 기능(필드변수, 메서드)이 복사 붙이기 되어 있는 것과 같다.
  • extends ScoreServiceImplV1명령문을 클래스 뒤에 붙였기 때문에
 
  • ScoreSerivceImplV1의 모든 기능 중 scoreList() method의 코드를 바꾸어 작성하고 싶다.
  • 단, 나머지 기능은 V1의 것을 사용하고 싶다.
@Override // << 지워도 됌 재 정의된 표시라고 생각하면 됌.
public void scoreList() {
System.out.println("===================================================");
System.out.println("성적일람표 V2");
System.out.println("===================================================");
System.out.println("학번\t국어\t영어\t수학\t총점\t평균");
System.out.println("---------------------------------------------------");
    for(ScoreVO sVO : scoreList) {  // V1의 for문을 향상된 for문으로 변경한 V2
        System.out.print(sVO.getNum() + "\t");
        System.out.print(sVO.getKor() + "\t");
        System.out.print(sVO.getEng() + "\t");
        System.out.print(sVO.getMath()+ "\t");
        System.out.print(sVO.getSum()+ "\t");
        System.out.println(sVO.getAvg());
}
System.out.println("===================================================");
}
>>>>>>>> service > ScoreServiceImplV2🙂

인터페이스를 사용하는 방법

  • ex) List< > = new ArrayList<>
  • 실제코드가 담겨있는 V1를 이용해서 초기화함
  • interface를 implements하여 만들어진 클래스는
  • 선언을 할 때는 interface로 선언을 하고,
  • 초기화 할때는 실제 코드가 구현된 클래스로 초기화 한다.
  • ScoreService sService = new ScoreServiceImplV1();
sService.inputScore();
sService.calcSum(); 
sService.calcAvg(); // 여기에는 아무것도 없는데 인풋스코어 메서드랑 스코어리스트는 하는 일이 있으니까 해놔도 오류없이 잘 실행
sService.scoreList();
* List interface는 ArrayList 클래스를 선언할 때 implements한 주체이다.
* 따라서 ArrayList형 객체(인스턴스)를 만들때는 
* 선언은 List로 하고, 초기화는 ArrayList로 수행한다.
List<String> strList = new ArrayList<String>(); // 이 코드로 많이 사용하라! // 일반 
strList = new LinkedList<String>(); 
strList = new Vector<String>();
ArrayList<String> strList1 = new ArrayList<String>(); // 이거보다는
>>>>>>>> score > ScoreEx_01🙂
service
중요한 연산을 담당하는 클래스
 
클래스를 만들때 필드변수,속성, 등등 여러가지
필드변수에는 별다른 값을 추가하지않는게 좋음
선언만된 친구는 준비가 되어있지 않은데 = new해버리면 메모리에 너무오래남아있어서
 
기본생성자를 만들고 생성자를 만들어줘야함
public Service() {
    voList = new ArrayList<VO>();
}
저 스코프를 벗어나면 소멸되기때문에 소멸자는 따로 없다.
객체 지향 프로그램 의 특징 중 하나는
필드 변수를 private으로 설정하고
접근 getter, setter를 사용해서 클래스 정의하는 것을 정보은닉, 캡슐화 라고 한다!
무슨일이 벌어지는지는 모르지만 뭔 일을 하는지는 알아 << 투명성!
캡슐화랑 투명성은 같은
상속 재정의
중복정의 << 오버로딩
객체지향의 5대 특징 : 상속, 메서드의 재정의, 중복정의(오버로딩) VO의 필드변수 private으로 만들고 getter와 setter가 붙더라 이걸 정보의 캡슐화
캡슐화 : 내부에서 어떤일들이 어떻게 벌어지는지는 모르지만
getter는 값 가져오기
setter는 값 저장하기 로 알고 있는거 ex) 의사선생님이 캡슐 색깔보고 무슨 역할을 하는 약인지 아는 것 처럼

 

캡슐화, 정보은닉은 더 배울 예정
  • 정보의 유효성 검사
 
// 현재 국어점수 필드에 저장하려고 하는 값이 유효한 값인가를 검사
// 성적은 0 ~ 100 까지가 기본값인데
// 만약에 성적을 0미만, 100초과 된 값을 저장하려고 하면
// 거부하도록 setKor() 변경
public boolean setKor(int kor) {
if( kor < 0 || kor > 100) {
return false;
}
this.kor = kor;
return true;
}
System.out.print("국어 >> ");
String strKor = scan.nextLine();
int intKor = 0;
try {
    // 문자열로 받았기 때문에 문자열을 숫자로 바꿔주는 
    intKor = Integer.valueOf(strKor);
} catch (Exception e) {
    System.out.println("국어는 숫자만 가능합니다.");
    System.out.println("입력이 잘못되어 0으로 임시 저장합니다.");
}
// >> intKor는 0인 상태로 유지가 된다.
if(!scoreVO.setKor(intKor)) {
    System.out.println("국어 점수는 0 ~ 100 까지만 가능");
    System.out.println("국어 점수는 임시로 0으로 저장합니다.");
} // >>> 유효성 체크해주는 부분
728x90