Notice
Recent Posts
Recent Comments
05-18 00:26
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

Byeol Lo

Computer Language - OOP (1) 본문

Programming Language/Java

Computer Language - OOP (1)

알 수 없는 사용자 2023. 5. 1. 14:27

Axiom - "모든 것은 객체로 이루어져 있다."를 머리 속에 담고 읽자.

 

Class(클래스)

 객체들은 클래스로 부터 생성된다. 클래스는 설계도이다. 우리가 조립할 때, 각 부품들을 설명서에 맞게 조립하듯이 클래스는 객체를 만들기 위한 설계도(Frame/Blueprint)에 해당한다. (물론 각 부품들도 객체라고 볼 수 있다.)

 

객체들은 서로 관계를 형성하면서 상호작용을 한다. 그 관계에는 다음과 같은 세 가지 유형이 있다

  • Association : 연관
  • Composition/Aggregation : 구성
  • Inheritance : 상속

위의 관계들에 의해서 모든 객체들은 서로서로 영향을 주면서 실제 세계를 가상 세계로 구현시킬 수 있다.

 

OOP(Objected Oriented Programming)

 모든 것들을 객체로 바라보는, 객체의 형태로 프로그래밍 하는 것을 객체 지향 프로그래밍이라고 한다. 다음과 같은 특징들이 있다.

  • Encapsulation(캡슐화) : 다른 객체로부터 세부 사항(내부 설계, 정보)들을 숨기거나 접근을 제한시킬 수 있도록 한다.
    • 장점 : 보안의 유연성이 높아지며, 세세한 보안 설정이 가능하다.
  • Inheritance(상속) : 하나의 객체가 가지고 있는 속성들(변수들, 정보들) 혹은 메소드들을 다른 객체에게 물려줄 수 있다.
    • Subclass(자식 클래스) : 다른 클래스에 의해 상속받은 클래스
    • Superclass(부모 클래스) : 다른 클래스에게 상속해주는 클래스
    • 장점 : 코드 중복성을 없애고, 효율적인 코딩이 가능하다. 다형성(Polymolphism)을 위한 설계를 할 수 있도록 한다.
  • Polymorphism(다형성) : 수많은 형태를 가질 수 있는 특성을 말한다. 보통 한 클래스에게 물려받은 것들을 토대로 다른 형태를 띄도록 수정을 하여 다양한 형태로 띄게 하는 것이다.
    • 장점 : 같은 액션(메소드)가 데이터 형에 따라 다른 방식으로 구현되도록 할 수 있다.

 

OOP를 Procedural programming과 비교했을때, OOP를 이용할 수 밖에 없는 장점들을 살펴보자.

  • Modularity : 어떤 코드들의 구성요소가 분리되고 재결합 할 수 있는 정도를 의미하며, OOP를 통해 작성한 코드들은 모듈화가 절차지향적 프로그래밍 보다 뛰어나다.
  • Information-hiding : 외부 객체로부터 세부 정보를 숨길 수 있다.
  • Code re-use : 코드 재사용 가능성이 높다.
  • Pluggability and debugging ease : 어떤 객체가 문제 발생시, 해당 객체를 빠르게 제거하고 디버깅이 가능하다.

 

Class Declaration

//Access modifier/Class decl'/Class name
public class Person {
    // Field
    String name;
    public int age;
    String sex;
    double satiety = 0.5;

    // Constructors
    Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    // Methods
    public void eat(String food) {
        System.out.println(name + " : " + food + " is Yummy!");
    }

    public void showSatietyRate() {
        System.out.println("포만감 : " + satiety);
    }

}
  • Field : 객체가 가질 수 있는 상태값들을 정의
  • Constructor : 객체가 생성될 때, 처음 자동으로 실행되는 코드
  • Method : 객체가 행위를 취하는, 행동하는 것을 정의

 

Instantiation(객체화, 인스턴스화)

 new를 통해 객체화를 하게 되며, 객체가 되기 전 Constructor를 호출하여 객체의 초기 설정을 진행한다. 그 후에 메모리 주소를 반환하게 된다.

public Main {
    public static void main(String[] args) {
    	Person person = new Person("hi", 12, "F"); // 객체화, Constructor을 수행 후 메모리 반환
    }
}

 보통 다음과 같이 클래스의 Constructor를 생략하여 사용할 수 있는데, 이는 JVM이 자동으로 기본 코드를 추가시켜준다. (반드시 아무 Constructor가 없을때 자동 추가시킨다.)

class Person {
    
//    Person () {}
    
    public void shout(String str1) {
        System.out.println(str1);
    }
}

주석으로 처리한 부분이 JVM이 자동으로 생성한 코드이다.

 

Class Import

클래스를 가져올 때 다음과 같은 문제점이 생길 수 있다.

//person/Person.java
package person;

public class Person {

    String name;
    public int age;
    String sex;
    double satiety = 0.5;


    Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public void eat(String food) {
        System.out.println(name + " : " + food + " is Yummy!");
    }

    public void showSatietyRate() {
        System.out.println("포만감 : " + satiety);
    }

}

// ============================================
// Main.java
import person.Person;

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
    }
}

class Person {

//    Person () {}

    public void shout(String str1) {
        System.out.println(str1);
    }
}

 이럴땐 어떤 것을 instantiation하는지 의문이 생길 수 있다. 하지만 이는 에러가 뜬다. 같은 class 명을 가지는 클래스를 선언했기 때문이다. 하지만 다음과 같이 파일을 각기 다른 곳에 선언했다고 하자.

// src/Main.java
import person.Person;

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        
    }
}
// src/Person.java
public class Person {
    public void shout(String str1) {
        System.out.println(str1);
    }
}
// src/person/Person.java
package person;

public class Person {

    String name;
    public int age;
    String sex;
    double satiety = 0.5;


    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public void eat(String food) {
        System.out.println(name + " : " + food + " is Yummy!");
    }

    public void showSatietyRate() {
        System.out.println("포만감 : " + satiety);
    }

}

 이럴땐 person.Person을 import 했기 때문에 Person을 호출했을때, person/Person.java를 가져오게 된다. 만약 import가 없었다면, src/Person.java를 가져왔을 것이다. 따라서 import로 선언한 것이 파일 위치보다 더 우선시 된다. 또한 src/Person.java 파일을 다른 패키지에 넣어 Main.java에서 import를 하더라도 이미 person.Person을 import했기 때문에 에러가 뜨게 된다. 이럴때 다 쓸 수 있는 방법이 있는데, 바로 import를 하지 않고 쓰는 것이다.

// src/Main.java

public class Main {
    public static void main(String[] args) {
        person.Person person1 = new person.Person("name", 12, "Female");
        person2.Person person2 = new person2.Person();
        person3.Person person3 = new person3.Person();

        person1.showSatietyRate();
        person2.shout("Hello");
        person3.eat();
    }
}
// src/person/Person.java

package person;

public class Person {
    String name;
    public int age;
    String sex;
    double satiety = 0.5;

    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public void eat(String food) {
        System.out.println(name + " : " + food + " is Yummy!");
    }

    public void showSatietyRate() {
        System.out.println("포만감 : " + satiety);
    }
}
// src/person2/Person.java

package person2;

public class Person {
    public void shout(String str1) {
        System.out.println(str1);
    }
}
// src/person3/Person.java

package person3;

public class Person {
    public void eat() {
        System.out.println("Yummy!");
    }
}

이렇듯 직접 경로들을 . 연산자를 통해 객체, 패키지, 메소드, 필드 등에 접근을 하여 직접 선언해주면 된다.

 

Multiple Constructors

 하나의 클래스 내부에 하나의 constructor만 있다면, 해당 클래스가 가지는 특성(값, 멤버변수)는 표현력이 매우 적을 것이다. 가령 하나의 차가 버전이 다르다면, 해당 버전을 부르는 명칭도 달라야 할 것이다. 이때, 쓸 수 있는 것이 Multiple Constructor이다.

// src/Main.java

import minecraft.Minecraft;

public class Main {
    public static void main(String[] args) {
        Minecraft minecraft1 = new Minecraft();
        Minecraft minecraft2 = new Minecraft("bedrock");
        Minecraft minecraft3 = new Minecraft(152);

        minecraft1.showName();
        minecraft2.showName();
        minecraft3.showName();
    }
}
// src/minecraft/Minecraft

package minecraft;

public class Minecraft {
    static int sales = 1;
    int id;
    int version;
    String edition;

    public Minecraft(int version, String edition) {
        this.version = version;
        this.edition = edition;
        this.id = sales;
        sales++;
    }

    public Minecraft(int version) {
        this(version, "java");
    }

    public Minecraft(String edition) {
        this(1194, edition);
    }

    public Minecraft() {
        this(1194, "java");
    }

    public void showName() {
        System.out.println("===== " + id + "'th Minecraft =====");
        System.out.println("version: " + version);
        System.out.println("edition: " + edition);
    }
}

이때, Multiple Constructor을 씀으로써 코드 재활용성이 매우 높아지고, 인스턴스의 유연성도 높아졌다.

'Programming Language > Java' 카테고리의 다른 글

Computer Language - OOP (3)  (0) 2023.09.15
Computer Language - OOP (2)  (0) 2023.09.15
Computer Language - Reference Type  (0) 2023.05.01
Computer Language - Condition & Loop  (2) 2023.04.30
Computer Language - Basic Operators  (2) 2023.03.22
Comments