카테고리 없음

[자바] 캡슐화, 상속, 추상화... 객체지향 모음

이앤지 2021. 11. 17. 20:54

캡슐화

더보기
package day0923;
/*캡슐화(Encapsulation)
 * 캡슐화란, 우리가 만드는 객체의 세부적인 내용을
 * 다른 곳에서는 알지 못하게 만드는 방법을 캡슐화라고 한다.
 * 
 * 모든 필드는 private 접근제한자를,
 * 메소드의 경우 외부가 쓸 메소드를 제외하고 나머지는 모두 private 접근 제한자를 적용시켜서
 * 외부에서 우리 클래스 객체를 만들어서 쓸 때
 * 굳이 세부적인 내용을 알 필요 없이 객체 그 자체를 사용하라는 의미가 된다!
 * 
 * 단 private 필드의 경우, 외부에서의 접근이 불가능하기 때문에
 * 메소드를 사용하여 값을 저장하거나 저장된 값을 호출해야 한다.
 * 이렇게 private 필드의 값을 저장/호출 하는 메소드를
 * 우리는 getter/ setter 라고 부른다.
 * 
 * setter는 다음과 같은 양식을 따른다.
 * public void set필드명(필드타입 필드명){
 *      this.필드명 = 필드명;
 * }
 * 
 * getter는 다음과 같은 양식을 따른다.
 * public 필드타입 get필드명(){
 *      return 필드명;
 * }
 * 
 * 
 * 만약 해당 필드에 외부의 값을 저장할 메소드가 없다면?
 * 당연히 해당 필드의 setter 메소드는 만들어주지 않는다.
 * 
 * 만약 해당 필드의 값을 외부가 알 필요가 없다면?
 * 당연히 해당 필드의 getter 메소드는 만들어주지 않는다.
 * 
 */

public class Ex01Encapsulation {
    

}

 

상속

더보기
package day0923;
/*상속(Inheritance)
 * 상속이란, 부모 클래스의 메소드 혹은 필드를 자식 클래스가
 * 또 적어주지 않더라도 그대로 받아서 쓸수 있게 만들어 주는 것을
 * 상속이라고 한다.
 * 
 * 상속은 사실 클래스 상속과 인터페이스 상속으로 나뉘는데
 * 클래스 상속의 목적은 코드의 재사용성을 높이기 위해
 * 인터페이스 상속의 목적은 다형성(Polymorphism)을 위함이다.
 * 
 * 상속을 하는 방법:
 * public class 자식클래스 extends 부모클래스 {
 * 
 * }
 * 
 * 
 * 자식 클래스의 객체를 초기화할 때에는
 * 부모 클래스의 생성자가 먼저 호출되고 그 다음에 자식 클래스의 생성자가 호출이 된다!
 * 
 * 오버라이드(Override)
 * 오버라이드란 부모클래스로부터 상속받은 메소드가
 * 자식 클래스가 사용하기 부적절한 경우,
 * 자식 클래스에서 재정의를 하여, 자식 클래스가 적절하게 사용할 수 있도록
 * 상속받은 메소드를 "덮어씌우는것"을 오버라이드라고 한다.
 * 단, 오버라이드를 할 시에 주의할 점은
 * 부모클래스가 선언한대로 똑같이 선언해주어야 한다는 것이다.
 * 
 * java.lang.Object
 * Object란? 객체를 뜻한다(Object Oriented Programming -> 객체 지향 프로그래밍
 * 자바의 모든 클래스는 java.lang.Obect를 직접적으로나 간접적으로나 상속을 받는다.
 * 이 java.lang.Object는 말 그대로 클래스들의 원본이라고 할 수 있는데
 * 이 Object라는 클래스 안에는
 * 객체를 상ㅇ하는데 필요한 몇가지 메소드들이 만들어져 있다.
 * 대표적으로, 기본형 데이터타입 필드는 0으로, 참조형 데이터타입 필드는 null로 초기화해주는
 * 기본생성자,
 * 두 객체가 같은지 비교해주는 equals() 메소드
 * 객페의 정보를 String으로 변환해주는 toString() 메소드 등이 있다.
 * 
 * 하지만, java.lang.Object의 메소드들은
 * 매우 두루뭉실하게 구현이 되어있다.
 * 예를 들어서, equals() 메소드 같은 경우에는
 * 어떤 객체의 특정 필드 값을 비교하여 결과를 보여주는 것이 아니라
 * 단순하게 주소값 비교를 하게 구현이 되어있다.
 * toString()을 포함한 다른 메소드들도 우리가 직접 쓰기에는
 * 불편하게 구현이 되어있으므로
 * 만약 equals()나 toString()과 같은 메소드를 우리 객체에 맞춰서 쓸려면
 * 우리가 직접 오버라이드를 해야한다!
 * 
 * 다형성(polymorphism)
 * 다형성이란 "다양한 모습을 지닌 성격"을 다형성이라고 한다.
 * 자바의 경우, 리턴타입, 생성자, 파라미터에 부모 클래스를 타입으로 적어주면
 * 자식 클래스도 그 자리에 들어갈 수 있다,
 * 단, 자식 클래스의 자리에는 부모 클래스가 들어갈 수 없다! 
 * 
 */

import classEx.Animal;
import classEx.Gorilla;
import classEx.Monkey;
import classEx.Student;

public class Ex02Inheritance {
    public static void main(String[] args) {
        Monkey a = new Monkey();
        a.setType("원숭이");
        a.makeSound();
        a.move();
        a.showInfo();
        
        Gorilla g = new Gorilla();
        a.setType("고릴라");
        a.makeSound();
        a.move();
        a.showInfo();
        
        Gorilla g2 = new Gorilla();
        
        System.out.println("g.equals(g2) "+g.equals(g2));
        String abc = new String("abc");
        System.out.println("g.equals(abc): "+g.equals(abc));
        
        Animal g3 = new Gorilla();
        
        
        //객체를 println()에 넣으면 어떻게 될까?
        //println()에 파라미터로 String클래스가 아닌 객체가 들어게가 된다면
        //그 클래스 객체의 toString()메소드가 실행되서 리턴된
        //String 값이 화면에 출력이 된다.
        
        //만약 별다른 toStirng() 오버라이드를 하지 않았을 경우
        //패키지.객체 클래스 @ 힙 메모리 주소값
        //이 리턴되서 출력된다.
        
        System.out.println(g);
        System.out.println(g3);
        
        // 씨유 엣 케이 리그
        // C Y @ 1d81eb93 K-league
        //주소에 메모리값이 남아있음
        
        Student s1 = new Student();
        s1.id = 1;
        s1.name = "조재영";
        s1.korean = 80;
        s1.english = 98;
        s1.math = 78;
        
        System.out.println(s1);
        

        
    }

}

 

추상화

더보기
package day0923;

import classEx.AnimalA;
import classEx.Dog;

// 추상클래스, 추상메소드, 인터페이스
// 클래스 상속은 우리가 코드의 재사용성을 높이기 위해 사용한다.
// 그에 반해서 추상클래스, 추상메소드, 그리고 인터페이스 상속은
// 코드의 재사용성보다는 다형성을 부여하기 위해 사용된다.

public abstract class Ex03Abastract {
    public static void main(String[] args) {
    // 추상 클래스는 구현되지 않은 메소드가 존재하므로
    // 해당 클래스의 생성자를 우리가 직접 호출할 수 없다.
    // 대신 그 클래스를 상속 받는 클래스의 생성자가 필요로 한다.
    
//    AnimalA a = new Dog();
//    a.makeSound();
//    a.move();
    
        
        AnimalA a = new Dog();
        observe(a);
        
        // 인터페이스도 추상 클래스와 매우 유사하지만
        // 달라지는 점은, 실제로 구현된는 메소드가 존재하는 추상 클래스와 다르게
        // 인터페이스는 모든 메소드가 추상 메소드란 것이다!
    
    
    }
    
    public static void observe(AnimalA a) {
        a.makeSound();
        a.move();
    }
    
    
}

 

인터페이스와 다형성

더보기
package day0923;

import util.ScannerUtil;
import classEx.MySqlConnector;
import classEx.DBConnector;
import classEx.OracleConnector;

import java.util.Scanner;

// 인터페이스를 활용하여
// 다형성 체험을 해보자
public class Ex04Interface {
    static DBConnector conn;
    static Scanner scanner = new Scanner(System.in);
    
    public static void main(String[] args) {
        conn = new OracleConnector();
        showMenu();
        
    }
    
    private static void showMenu(){
        String message = "1.Db연결 2.데이터입력 3.데이터전체출력 3.데이터개별출력 5.데이터수정 6.데이터삭제 7.ㅡㅍ로그램 종료";
        while(true) {
        int userChoice = ScannerUtil.nextInt(null, message, 1, 7);
                
        if(userChoice == 1) {
            conn.makeConnection();            
        } else if(userChoice == 2) {
            conn.insert();
        } else if(userChoice == 3) {
            conn.selectAll();
        } else if(userChoice == 4) {
            conn.seletOne();
        } else if(userChoice == 5) {
            conn.update();
        } else if(userChoice == 6) {
            conn.delete();
        } else if(userChoice == 7) {
            System.out.println("사용해주셔서 감사합니다.");
            conn.destroyConnection();
            break;
        }
        
        
        
    }
    }
}

 

객체지향 5대 원칙

package day0927;
/* 객체 지향의 5원칙
 * SOLID
 * S: 단일 책임 원칙 -> 클래스는 한번에 한가지의 책임만 가져야 한다.
 * O: 개방-폐쇄 원칙 -> 클래스는 확장에는 개방적이어야 하고 변화에는 폐쇄적이어야 한다.
 * L: 리스코프 원칙 -> 자식 클래스의 자리는 언제나 부모 클래스로 치환 가능하다.;다형성
 * I: 인터페이스 분리원칙 -> 인터페이스를 작은 사이즈로 만들어라
 * D: 의존성 역전 원칙 -> 추상화가 많이 된 클래스는 추상화가 많이 안된 클래스에 의존적인 관계여서는 안된다.
 * 
 * MVC패턴
 * MVC 패턴은 현재 가장 많이 사용되는 프로그래밍 패턴중에 하나로써
 * 여러분들의 클래스를 크게 3가지로 나누어서 분류하는 방법이다.
 * Model: 모델. 데이터를 담는 객체를 담당하는 클래스로써, 주로 이름 끝에 VO 혹은 DTO가 붙는 경우가 대부분이다.
 *        해당 클래스들은 클래스 안에 필드와 java.lang.Object 클래스의 오버라이드 메소드만 존재한다.
 * View: 뷰. 사용자가 보게 될 화면을 담당하는 클래스로써 UI라고 생각하면 편하다.
 *       컨트롤러가 보내준 데이터 혹은 사용자가 입력한 데이터를 컨트롤러로 보내주는 역할을 하게 된다.
 *       웹 프로그래밍의 경우, HTML이 뷰가 될 수도 있지만 현재 우리는 콘솔에서 프로그래밍 하므로 담당 클래스를 따로 만들어주면 된다.
 * Controller: 컨트롤러. 컨트롤러는 데이터베이스와의 통신을 담당하여 데이터베이스가 보내준 데이터를 객체의 모양으로 만들어주거나,
 *             뷰에서 보내준 객체의 형태의 데이터를 데이터베이스에 추가하는 등의 역할을 맡는다.
 * 
 * 
 */
종합 예제

더보기
package day0927;
/* 시간을 관리하는 Calendar
 * 
 * Calendar 클래스의 경우,
 * java.util.DateTime 이라는 클래스의 좀 더 세련된 버젼이다.
 * 기존의 DateTime은 더이상 사용되지 않는다.
 */

import java.text.SimpleDateFormat;
import java.util.Calendar;

public class Ex02Calender {
    public static void main(String[] args) {
        // Calendar 클래스 객체는 초기화할 때
        // 생성자가 아닌 Calendar 클래스의 getInstance() 라는 static 메소드를 통하여 초기화한다.
        Calendar cal = Calendar.getInstance();
        
        // Calendar 객체를 화면에 직접 출력해보자
        System.out.println(cal);
        
        // Calendar 클래스 객체의 경우
        // 그리니치 표준시간대 기준 1970년 1월 1일 0시 0분부터 현재 시간을
        // 1/1000 초로 저장하여 다루게 된다. -> 1632731714946
        
        // Calendar 객체의 필드 값들을 우리가 한 번 알아보자
        // 필드에 저장된 값을 호출할 때에는
        // 객체.get(필드명)으로 불러올 수 있다.
        
        System.out.println("연도: " + cal.get(Calendar.YEAR));
        // 월의 경우, 1~12 가 아닌 0~11로 설정되어 있다.
        System.out.println("월: " + cal.get(Calendar.MONTH));
        System.out.println("일: " + cal.get(Calendar.DAY_OF_MONTH));
        System.out.println("요일: "+ cal.get(Calendar.DAY_OF_WEEK));
        System.out.println("시(12시간 기준): "+cal.get(Calendar.HOUR));
        System.out.println("시(24시간 기준): "+cal.get(Calendar.HOUR_OF_DAY));
        System.out.println("분: "+cal.get(Calendar.MINUTE));
        System.out.println("초: "+cal.get(Calendar.SECOND));

        // Calendar 객체에 임의의 시간을 저장할 때는 set() 메소드를 사용하면 된다.
        // 이때에는 4가지 방법이 있다.
        // 1. 특정 필드에 특정 값을 넣는다.
        cal.set(Calendar.YEAR, 1999);
        System.out.println("연도: "+cal.get(Calendar.YEAR));
        
        // 2. 파라미터로 연도, 월, 일을 넣는다.
        cal.set(2002, 5, 20);
        System.out.println("연도: "+cal.get(Calendar.YEAR));
        System.out.println("월: " +cal.get(Calendar.MONTH));
        System.out.println("일: " +cal.get(Calendar.DAY_OF_MONTH));
        
        // 3. 파라미터로 연, 월, 일, 시, 분 를 넣는다.
        System.out.println("연도: "+cal.get(Calendar.YEAR));
        System.out.println("월: " + cal.get(Calendar.MONTH));
        System.out.println("일: " + cal.get(Calendar.DAY_OF_MONTH));
        System.out.println("시(24시간 기준): "+cal.get(Calendar.HOUR_OF_DAY));
        System.out.println("분: "+cal.get(Calendar.MINUTE));
        
        // 4. 파라미터로 연, 월, 일, 시, 분, 초를 넣는다.
        System.out.println("연도: "+cal.get(Calendar.YEAR));
        System.out.println("월: " + cal.get(Calendar.MONTH));
        System.out.println("일: " + cal.get(Calendar.DAY_OF_MONTH));
        System.out.println("시(24시간 기준): "+cal.get(Calendar.HOUR_OF_DAY));
        System.out.println("분: "+cal.get(Calendar.MINUTE));
        System.out.println("초: "+cal.get(Calendar.SECOND));
        
        //만약 우리가 캘린더 객체를 우리가 원하는 양식으로 출력하려면?
        //SimpleDateFormat 이라는 객체를 사용하여 출력해야 한다.
        //단, 캘린더 객체를 그대로 넣어주는 것이 아니라 현재 저장된 1/1000초 값인
        //time을 getTime() 이라는 메소드를 통해 넣어주어야 한다.
        
        SimpleDateFormat sdf;
        
        //SimpleDateFormat의 객체를 초기화할 때
        //파라미터있는 생성자를 선택해서 우리가 원하는 양식을 지정해준다.
        String format = new String("y년 M월 d일 h시 m분 s초");
        
        sdf = new SimpleDateFormat(format);
        
        // SimpleDateFormat 객체를 통하여 우리의 시간을 출력해보자
        System.out.println(sdf.format(cal.getTime()));
        
        
        // Calendar 객체의 경우, 기본적으로 lenient 라는 필드가 true로 되어있는데
        // 그 의미는 어느정도 유도리 있게 값 저장을 받겠다라는 뜻이 된다.
        // 즉, 해당 월의 날짜를 1~30 이 아닌 59 같은 날짜도 저장 가능하다.
        // 이때에는 자동으로 지정한 달 + 29일 째가 저장된다.
        cal.set(Calendar.DAY_OF_MONTH, 59);
        System.out.println(sdf.format(cal.getTime()));
        
        // 단, lenient를 false로 하면 범위를 벗어난 값을 입력시
        // 에러가 발생한다.
        cal.setLenient(false);
        cal.set(Calendar.DAY_OF_MONTH, 59);
        System.out.println(sdf.format(cal.getTime()));

        
    }
    
    

}

 

++ 맵

더보기
package day0930;
/*Map
 * 특정 데이터타입의 객체를 여러개 모아두는 Collection 중의 하나인 Map은
 * 우리가 객체를 저장하거나 저장된 객체를 호출할 때
 * 인덱스 번호값으로 제어하는 것이 아니라
 * 해당 객체에 접근 가능한 "키"값을 통해서 제어한다.
 * 
 */

import java.util.HashMap;

import classEx.Student2;

public class Ex01Map {
    public static void main(String[] args) {
        HashMap<String, Student2> map = new HashMap<>();
        
        Student2 s = new Student2();
        s.setId(1);
        s.setName("조재영");
        s.setKorean(80);
        s.setEnglish(80);
        s.setMath(81);
        
        map.put("s1", s); //String이 키값.
        
        System.out.println("map.get(\"s1\").getName(): " +map.get("s1").getName()); //키값을 불러와야됨
        System.out.println("map.get(\"s2\"): " +map.get("s2")); //키값을 불러와야됨

        for(int i = 0; i<10; i++) {  //10개의 객체 추가
            s = new Student2();
            s.setId(i+2);
            s.setName("학생"+i);
            s.setKorean(i*10);
            s.setEnglish(i*11);
            s.setMath(i*12);
            map.put("s"+i, s);
        }
        
        System.out.println("map.size(): "+map.size());
        System.out.println("map.get(s1).getName(): "+map.get("s1").getName());
        
        System.out.println("map.keySet(): "+map.keySet()); //keySet()메소드
        
        for(String str : map.keySet()) {
            Student2 temp = map.get(str); //들어가는 순서는 모름; 키셋에 들어가는 순서 상관없어서 몰라도 됨.
        }
        
    }
    
    
    
}