ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [자바 코딩 인터뷰 완벽 가이드] Chapter 6. 객체지향 프로그래밍 Part1
    STUDY/JAVA 2024. 8. 7. 17:24

    6.1 객체지향 프로그래밍의 개념 이해

    • 객체(object)
    • 클래스(class)
    • 추상화(abstraction)
    • 캡슐화(encapsulation)
    • 상속(ingeritance)
    • 다형성(polymophism)
    • 연관(association)
    • 집약(aggregation)
    • 구성(composition)

     

    6.1.1 객체란 무엇인가?

    • 객체는 객체지향 프로그래밍의 핵심 개념 중 하나이다.
    • 객체는 실세계의 개체이다.
    • 객체는 상태(필드)와 동작(메서드)를 가진다.
    • 객체는 클래스의 인스턴스를 나타낸다.
    • 객체는 메모리에서 공간을 차지한다.
    • 객체는 다른 객체와 소통할 수 있다.
    • 객체는 각기 다른 접근 제어자(access modifier) 및 가시성 범위를 가질 수 있다.
    • 객체는 가변 또는 불변 속성을 가진다.
    • 객체는 가비지 컬렉터(garbage colletor)를 통해 수집된다.
    객체는 객체지향 프로그래밍의 핵심 개념 중 하나로, 차, 탁자, 고양이와 같은 실세계의 개체와 같다. 수명주기(life cycle)동안 객체는 상태와 동작을 가진다. 자바에서 객체는 new 키워드를 통해 만들어진 클래스의 인스턴스로 필드에 상태를 저장하고 메서드로 동작을 표현한다. 각 인스턴스는 메모리 공간을 차지하며 다른 객체와 소통할 수 있다.

     

     

    6.1.2 클래스란 무엇인가?

    • 클래스는 객체지향 프로그래밍의 핵심 개념 중 하나이다.
    • 클래스는 객체를 생성하기 위한 템플릿 또는 청사진이다.
    • 클래스는 인스턴스화하기 전까지는 메모리의 힙 영역을 소모하지 않는다.
    • 클래스는 여러 번 인스턴스화할 수 있다.
    • 하나의 클래스는 하나의 작업만 한다.
    • 클래스는 각기 다른 접근 제어자 및 가시성 범위를 가질 수 있다.
    • 클래스는 로컬, 클래스 그리고 인스턴스 변수 등 다양한 타입의 변수를 지원한다.
    • 클래스는 abstract, fianl 또는 private으로 선언할 수 있다.
    • 클래스는 다른 클래스(내부 클래스)에 중첩될 수 있다.
    클래스는 객체지향 프로그래밍의 핵심 개념 중 하나로, 특정 타입의 객체를 만드는 데 필요한 지침의 집합이다. 클래스는 템플릿, 청사진 또는 객체를 만드는 방법을 알려주는 레시피하고 할 수 있으며, 객체를 만드는 과정을 '인스턴스화한다'고 하며 new 키워드로 수행할 수 있다. 클래스는 여러 번 인스턴스화하여 원하는 만큼 많은 객체를 만들 수 있다. 클래스의 정의는 파일 형태로 하드 드라이브에 저장될 뿐 메모리의 힙 영역을 소모하지 않는다. 클래스는 단일 책임 원칙을 따르고, 이 원칙에 따라 단 하나의 일을 할 수 있도록 설계 및 작성되어야 한다.

     

     

    6.1.3 추상화란 무엇인가?

    • 추상화는 객체지향 프로그래밍의 핵심 개념 중 하나이다.
    • 추상화는 사용자와 관련 있는 내용만 노출하고 나머지 세부 내용은 숨기는 개념이다.
    • 추상화를 통해 사용자는 애플리케이션이 일을 수행하는 방법이 아니라 애플리케이션이 수행하는 일 자체에 집중할 수 있다.
    추상화는 사용자를 위해 무언가를 최대한 간단하게 만들고자 하는 객체지향 프로그래밍의 핵심 개념 중 하나이다. 객체지향 프로그래밍의 객체는 사용자에게 높은 수준의 작업 집합만 노출하고 작업의 내부 구현 내용은 숨겨야 한다는 말이 있다. 이 개념을 구현하는 추상화를 통해 사용자는 애플리케이션이 일을 수행하는 방법이 아니라 수행하는 일 자체에 집중할 수 있다. 즉, 내용을 노출하는 복잡성을 줄이고 코드의 재사용성을 높이며 코드 중복을 방지하고 낮은 결합도와 높은 응집도를 유지한다. 또한 중요한 내용만 공개하여 애플리케이션의 보안과 재량권을 유지한다.

     

    [예시]

    차를 운전하는 사람이 있을 때, 사람은 각각의 페달이 무슨 일을 하는지, 핸들이 무슨 일을 하는지 알고 있지만, 페달과 핸들에 힘을 실어주는 차 내부의 메커니즘은 전혀 알지 못하는 경우가 많다. 이것이 추상화이다.

    public interface Car {
        public void speedUp();
        public void slowDown();
        public void turnRight();
        public void turnLeft();
        public String getCarType();
    }
    
    
    public class ElectricCar implements Car {
        private final String carType;
        
        public ElectricCar(String carType) {
        	this.carType = carType;
        }
        
        @Override
        public void speedUp() {
        	... 구현 내용
        }
        
        @Override
        public void slowDown() {
        	.. 구현 내용
        }
        
        @Override
        public void turnRight() {
        	.. 구현 내용
        }
        
        @Override
        public void turnLeft() {
        	.. 구현 내용
        }
        
        @Override
        public String getCarType() {
        	return this.carType;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
        	Car electricCar = new ElectricCar("BMW");
        	Car petrolCar = new ElectricCar("Audi");
            
            System.out.println("Driving the electric car: " + electricCar.getCarType() + "\n");
            electricCar.speedUp();
            electricCar.turnLeft();
            electricCar.slowDown();
            
            System.out.println("\n\nDriving the petrol car: " + petrolCar.getCarType() + "\n");
            petrolCar.slowDown();
            petrolCar.turnLeft();
            petrolCar.turnRight();
        }
    }

     

     

    6.1.4 캡슐화란 무엇인가?

    • 캡슐화는 객체지향 프로그래밍의 핵심 개념 중 하나이다.
    • 캡슐화는 객체 상태가 외부로부터 숨겨진 상황에서 이 상태에 접근하는 일련의 공개 메서드만 노출하는 기법이다.
    • 캡슐화는 각 객체가 클래스 내에서 객체의 상태를 비공개로 유지할 때 성립한다.
    • 캡슐화는 정보 은닉(infomation-hiding) 메커니즘이라고도 한다.
    • 캡슐화는 느슨한 결합, 재사용성, 보안 및 테스트하기 쉬운 코드와 같은 여러가지 중요한 이점을 제공한다.
    • 캡슐화는 접근 제어자로 구현할 수 있다.
    캡슐화는 객체지향 프로그래밍의 핵심 개념 중 하나로, 주로 코드와 데이터를 하나의 작업 단위인 클래스로 결합하고 외부 코드가 이 데이터에 직접 접근하지 못하게 하는 방어막 역할을 한다. 또한 객체 상태를 외부로부터 숨기고 이 상태에 접근하기 위한 일련의 public 메서드를 노출하는 기법이다. 각 객체가 클래스 안에서 상태를 private으로 유지할 때 캡슐화가 성립되었다고 할 수 있다. 따라서 캡슐화는 정보 은닉 메커니즘이라고 불리기도 한다. 캡슐화를 이용하면 몇 가지 장점이 있는데, 먼저 코드의 느슨한 결합이 가능하다. 예를 들어 클라이언트 코드와 어긋나지 않는 상태에서 클래스 변수의 이름을 변경할 수 있다. 또한 재사용할 수 있으며 클래스 내에서 데이터가 어떻게 조작되는지 클라이언트가 인식하지 못하므로 안전하다. 자바에서 캡슐화는 public, private, protected와 같은 접근 제어자로 구현할 수 있다. 일반적으로 객체가 자체 상태를 관리할 때 상태는 private 변수로 선언되고 public 메서드로 접근 및 수정되고, 클래스 외부에서 접근할 수 없는 private 메서드도 가질 수 있다.

     

    [예시]

    public class Cat {
        private int mood = 50;
        private int hungry = 50;
        private int energy = 50;
        
        public void sleep() {
        	energy++;
            hungry++;
        }
        
        public void play() {
        	mood++
        	energy--;
        }
        
        public void feed() {
            hungry--;
            mood++;
        }
        
        private void meow() {
        	...
        }
        
        public int getMood() {
        	return mood;
        }
        
        public int getHungry() {
        	return hungry;
        }
        
        public int getEnergy() {
        	return energy;
        }
    }
    
    
    public static void main(String[] args) {
        Cat cat = new Cat();
        
        cat.feed():
        cat.play();
        cat.feed();
        cat.sleep();
    }

     

     

    6.1.5 상속이란 무엇인가?

    • 상속은 객체지향 프로그래밍의 핵심 개념 중 하나이다.
    • 상속을 통해 다른 객체를 기반으로 하는 새로운 객체를 만들 수 있다.
    • 상속은 객체가 다른 객체의 코 드를 재사용할 수 있도록 허용하여 코드의 재사용성을 유지한다. 또한 각 객체만의 로직도 추가할 수 있다.
    • 상속은 IS-A 관계라고 하며, 부모-자녀 관계라고도 한다.
    • 자바에서 상속은 extends 키워드로 구현할 수 있다.
    • 상속된 객체는 슈퍼클래스라고 하고, 슈퍼클래스를 상속받은 객체는 서브클래스하고 한다.
    • 자바에서는 여러 개의 클래스를 상속할 수 없다.
    상속은 객체지향 프로그래밍의 핵심 개념 중 하나이다. 상속을 통해 다른 객체를 기반으로 객체를 만들 수 있다. 상속은 서로 다른 객체가 상당히 유사하고 몇 가지 공통된 로직을 공유하지만 완전히 동일하지는 않을 때 유용하다. 상속은 객체가 다른 객체의 코드를 재사용할 수 있도록 허용하여 코드의 재사용성을 유지하고 각 객체만의 로직도 추가할 수 있다. 이를 IS-A 관계라고 하며 부모-자녀 관계라고도 한다. 예를 들어 '고양이 IS-A 고양이과의 동물' 또는 '기차 IS-A 교통수단' 과 같이 상속 관계를 표현할 수 있다. 자바에서 상속은 extends 키워드로 부모 클래스로부터 자식 클래스를 파생시켜 구현한다. 상속된 객체는 슈퍼클래스 또는 부모 클래스하고 하고 슈퍼클래스를 상속받은 객체는 서브클래스 또는 자식 클래스라고 하며, 자바에서는 여러 개의 클래스를 상속할 수 없다.

     

    [예시]

    public class Employee {
        private String name;
        
        public Employee(String name) {
        	this.name = name;
        }
    }
    
    public class Programmer extends Employee {
        private String team;
        
        public Programmer(String name, String team) {
        	super(name);
            this.team = team;
        }
    }

     

     

    6.1.6 다형성이란 무엇인가?

    • 다형성은 객체지향 프로그래밍의 핵심 개념 중 하나이다.
    • 다형성을 뜻하는 'polymorphism'이라는 단어는 그리스어로 '많은 형태'를 의미한다.
    • 다형성은 때에 따라 객체가 다르게 동작할 수 있도록 한다.
    • 다형성은 (컴파일 타임 다형성이라고 하는) 메서드 오버로딩(overloading)이나, IS-A 관계의 경우(런타임 다형성이라고 하는) 메서드 오버라이딩을 통해 형성될 수 있다.
    다형성은 객체지향 프로그래밍의 핵심 개념 중 하나로, 객체가 때에 따라 다르게 동작할 수 있게 해주거나 어떤 종작이 다른 방법으로 동작할 수 있도록 하는 역할을 한다. 다형성을 구현하는 방법 중 하나는 메서드 오버로딩이 있다. 여러 개의 메서드가 동일한 이름을 가지고 있지만 매개변수가 다른 경우 컴파일러가 오버로드된 메서드 가운데 어떤 형식을 호출할 것인지 컴파일 시간에 식별할 수 있으므로 컴파일 타임 다형성이라도고 한다. 또 다른 방법은 메서드 오버라이딩이 있다. 메서드 오버라이딩은 IS-A 관계가 있을 때 일반적으로 사용하는 방법이며, 런타임 다형성 또는 동적 메서드 디스패치라고도 한다. 보통 여러 가지 메서드를 포함하는 인터페이스 구현으로 시작하며, 각 클래스는 특화된 동작을 수행하기 위해 인터페이스에 있는 메서드를 오버라이드한다. 이때 다형성이 타입에 대한 혼란 없이 이 클래스들을 부모 인터페이스와 똑같이 사용할 수 있게 하는데, 런타임에 자바가 이런한 클래스를 구별할 수 있고 어느 클래스가 사용되는지 알고 있기 때문에 가능한 일이다.

     

    [예시] 메서드 오버로딩을 활용한 컴파일 타임 다형성

    public class Triangle {
        public void draw() {
        	System.out.println("Draw default triangle...");
        }
        
        public void draw(String color) {
        	System.out.println("Draw a triangle of color " + color);
        }
        
        public void draw(int size, String color) {
        	System.out.println("Draw a triangle of color " + color + " and scale it up with the new size of " + size);
        }
    }

     

    [예시] 메서드 오버라이딩을 활용한 런타임 다형성

    public interface Shape {
        public void draw();
    }
    
    public class Triangle implements Shape {
        @Override
        public void draw() {
            System.out.println("Draw a triangle ...");
        }
    }
    
    public class Rectangle implements Shape {
        @Override
        public void draw() {
            System.out.println("Draw a rectangle ...");
        }
    }
    
    public class Circle implements Shape {
        @Override
        public void draw() {
            System.out.println("Draw a circle ...");
        }
    }

     

     

    6.1.7 연관이란 무엇인가?

    • 연관은 객체지향 프로그래밍의 핵심 개념 중 하나이다.
    • 연관은 서로 독립적인 두 클래스 간의 관계를 의미한다.
    • 연관은 소유자가 없다.
    • 연관은 일대일, 일대다, 다대일, 다대다 관계가 될 수 있다.
    연관은 객체지향 프로그래밍의 핵심 개념 중 하나로, 서로 독립적인 두 클래스 간의 관계를 의미하여 객체 간의 다중 관계라고도 한다. 연관에서는 소유자가 없다. 연관 관계에 있는 객체들은 서로 사용 가능한 양방향 연관 관계를 가지거나 한 객체만 다른 객체를 사용할 수 있는 단방향 연관 관계를 가지며 자체 수명을 가진다. 예를 들어 사람과 주소 객체에는 양방향 다대다 관계가 있을 수 있다. 한 명의 사람은 여러 개의 주소와 연관될 수 있으며 하나의 주소는 여러 사람에게 속할 수 있다. 그러나 사람은 주소 없이 존재할 수 있고 주소도 사람 없이 존재할 수 있다.

     

    [예시]

    public class Person {
        private String name;
        
        public Person(String name) {
            this.name = name;
        }
    }
    
    public class Address {
        private String city;
        private String zip;
        
        public Address(String city, String zip) {
        	this.city = city;
            this.zip = zip;
        }
    }
    
    public static void main(String[] args) {
        Person p1 = new Person("Andrei");
        Person p2 = new Person("Marin");
        Address a1 = new Address("Banesti", "107050");
        Address a2 = new Address("Bucuresti", "229344");
        
        System.out.println(p1.getName() + " lives at address " + a2.getCity() + ", " + a2.getZip() + " but it  also has an address at " + a1.getCity() + ", " + a1.getZip());
        System.out.println(p2.getName() + " lives at address " + a1.getCity() + ", " + a1.getZip() + " but it  also has an address at " + a2.getCity() + ", " + a2.getZip());
    }

     

     

    6.1.8 집약이란 무엇인가?

    • 집약은 객체지향 프로그래밍의 핵심 개념 중 하나이다.
    • 집약은 단방향 연관 관계의 특별한 경우이다.
    • 집약은 HAS-A 관계를 나타낸다.
    • 집약 관계에 있는 두 객체는 자체 수명 주기를 가지며 객체 중 하나는 HAS-A 관계의 소유자이다.
    집약은 객체지향 프로그래밍의 핵심 개념 중 하나이다. 집약은 단방향 연관 관계의 특별한 경우이다. 연관이 서로 독립적인 두 클래스 간의 관계를 의미한다면 집약은 두 객체 간의 HAS-A 관계를 의미한다. 여기서 집약 관계의 두 객체는 자체 수명 주기를 가지며 객체 중 하나는 HAS-A 관계의 소유자이다. 자체 수명 주기를 갖는다는 것은 한 객체가 종료되어도 다른 객체에 영향을 미치지 않는다는 의미이다. 예를 들어 테스트 선수는 라켓을 가지는데, 라켓은 테니스선수를 사용할 수 없으므로 단방향 연관 관계이고, 테니스 선수가 죽더라도 라켓은 영향을 받지 않는다.

     

    [예시]

    public clas Racket {
        private String type;
        private int size;
        private int weight;
        
        public Racket(String type, int size, int weight) {
        	this.type = type;
            this.size = size;
            this.weight = weight;
        }
    }
    
    public class TennisPlayer {
        private String name;
        private Racket racket;
        
        public TennisPlayer(String name, Racket racket) {
        	this.name = name;
            this.racket = racket;
        }
    }
    
    public static void main(String[] args) {
        Racket racket = new Racket("Babolat Pure Aero", 100, 300);
        TennisPlayer player = new Tennisplayer("Rafael Nadal", racket);
    }

     

     

    6.1.9 구성이란 무엇인가?

    • 구성은 객체지향 프로그래밍의 핵심 개념 중 하나이다.
    • 구성은 좀 더 제한적인 집약 관계이다.
    • 구성은 단독으로 존재할 수 없는 객체를 포함하는 HAS-A 관계를 나타낸다.
    • 구성은 코드 재사용성과 객체의 가시성 제어를 유지한다.
    구성은 객체지향 프로그래밍의 핵심 개념 중 하나로, 좀 더 제한적인 집약 관계이다. 집약이 자체 수명 주기를 가지는 두 객체 간의 HAS-A 관계를 의미한다면, 구성은 단독으로 존재할 수 없는 객체를 포함하는  HAS-A 관계를 의미한다. 이러한 연결고리를 강조하기 위해 PART-OF 관계라고도 한다. 예를 들어 차는 엔진을 가지는데, 차가 파괴되면 엔진도 파괴되는 것을 의미한다. 구성은 객체의 가시성을 제어하고 코드를 재사용하므로 상속보다 더 낫다고 말한다.

     

    [예시]

    public class Engine {
        pirvate String type;
        private int horsepower;
        
        public Engine(String type, int horsepower) {
        	this.type = type;
            this.horsepower = horsepower;
        }
    }
    
    public class Car {
        private final String name;
        private final Engine engine;
        
        public Car(String name) {
            this.name = name;
            
            Engine engine = new Engine("petrol", 300);
            this.engine = engine;
        }
    }

     

     

     

     

    출처 : 안겔 레오나르드, 『자바 코딩 인터뷰 완벽 가이드』, 동양북스(2022), p105-p126

Designed by Tistory.