OOP in Java

김민욱·2025년 10월 19일

Object

세상의 모든 것은 객체다.

  • Identity
  • State
  • Behavior

Object-Oriented Programming

객체와 객체간의 관계, 상호작용을 기반으로 프로그램을 설계하는 패러다임.

  • Information Hiding & Encapsulation
  • Inheritance
  • Polymorphism

OOP in Java

객체를 클래스(Class)로 구현한다.

  • Identity -> Instance Reference로 구현
  • State -> Class의 Data Field로 구현
  • Behavior -> Class의 Method로 구현

클래스는 객체의 탬플릿. Alive(메모리에 올라감)하지 않다.
Class를 alive하게 만들기 위해서 필요한 것 -> 인스턴스(Instance)

뭔가를 만들고 싶다면? 클래스를 만들고 인스턴스화 하라!

class A {
	int x = 0; // Data Field -> State
    
    public void displayA() { // Method -> Behavior
    	System.out.println("This is A!");
    }
}

public class Main {
	public static void main(String[] args) {
    	System.out.println("Hello, Java!!");
        A myA = new A(); // Instance -> Identity!
    }
}

What is static?
클래스 수준에서 존재함.

static으로 선언된 변수나 메소드는 인스턴스가 아닌 클래스 자체에 속한다.
비-static 멤버는 객체가 생성될 때 마다 새로 메모리가 할당되지만 static 멤버는 클래스가 메모리에 로드될 때 단 한 번만 생성되어 모든 인스턴스가 해당 멤버를 공유한다.

static 메소드는 객체 없이 호출되므로 인스턴스 멤버(예: this, 비-static 변수/메소드)에 접근할 수 없다.
오직 다른 static 멤버만 직접 접근이 가능하다.

public class Example {
    int x = 10;
    static int y = 20;

    public static void print() { // static method
        // System.out.println(x); ❌ 인스턴스 변수 접근 불가
        System.out.println(y);   // ✅ static 변수 접근 가능
    }
    
    public void nonstaticPrint() { // non-static method
    	System.out.println(x); // ✅ 인스턴스 변수 접근 가능
        System.out.println(y); // ✅ static 변수 접근 가능
    }
}
  • static 접근 예제
public class A {
	int i = 5;
    static int k = 2;
    
    public static void main(String[] args) {
    	int j = i; // ❌ i는 인스턴스 멤버.
        m1(); // ❌ m1()은 인스턴스 메소드.
        
        A a = new A(); 
        int j = a.i; // ✅ 인스턴스를 통한 멤버 접근
        a.m1(); // ✅ 인스턴스를 통한 메소드 호출
    }
    
    public void m1() {
    	// ✅ 비-static 메소드는 static 메소드 호출 가능
    	i = i + k + m2(i, k);
    }
    
    public static int m2(int i, int j) {
    	// ✅ 여기서 i는 전달받은 인자.
    	return (int)(Math.pow(i,j));
    }
}
  • main은 왜 항상 static일까?
    자바 프로그램이 실행되면 JVM은 main() 메소드를 우선적으로 찾는다. 이 때 main() 메소드가 static이 아닐 경우 main() 메소드는 특정 객체에 소속된 인터페이스 메소드가 된다. 따라서 main을 호출하기 위해서 해당 클래스를 인스턴스화 해줘야 한다.
    JVM이 프로그램을 시작할 때 객체를 생성하지 않고 바로 호출하기 위해서 main()은 static이어야 한다.

Encapsulation in Java

Abstraction: 구현과 사용을 분리한다. 무엇을 할 것인가에 집중.
Encapsulation: 구현 상의 디테일을 사용자로부터 숨긴다. 어떻게 숨길 것인가에 집중.

Class는 Abstract Data Type(ADT)을 구현하는 도구이다.

  • Encapsulation 예제
public class Circle {
	// private Data Field.
    // User can not access directly.
	private double radius = 1;
    
    // Getter Method.
    // Data can be read only using Getter Method.
    public double getRadius() {
    	return radius;
    }
    
    public double getArea() {
    	return radius * radius * Math.PI;
    }
    
    // Setter Method.
    // Data can be changed only using Setter Method.
    public void setRadius(double newRadius) {
    	if (newRadius > 0) 
        	radius = newRadius;
        else 
        	radius = 0;
    }
}

Class Relationship: Has-A

  • Association
    두 클래스의 상호작용을 묘사하는 가장 범용적인 이항 관계.
    예) Student, Course, Faculty
    Student take Course.
    Faculty teach Course.

  • Aggregation
    Association에 두 클래스 사이의 소유권(Ownership)을 나타낸 관계.
    Owner Object = Aggregating Object
    Subject Object = Aggregated Object
    예) Student, Name
    Student has Name

  • Composition
    하나의 클래스만이 소유할 수 있는 경우(Aggregation이 1대1 관계인 경우) 이를 나타내는 관계.
    예) Student, Name, Address
    이름은 unique 하지만, 주소는 공유 가능하다.
    (예: 기숙사 룸메라면 주소가 같을 것이다.)
    따라서 Student와 Name의 관계는 Composition 관계.
    Student와 Address의 관계는 Aggregation 관계이다.

  • 정리
    Composition \subset Aggregation \subset Association

Class Relationship: Is-A

Inheritance: 상속
기존의 클래스(Superclass)로부터 뻗어 나온 새로운 클래스(Subclass)를 정의하는 것이 가능하다.

  • Superclass
    범용적인 상위 클래스
public class GeometricObject {
	private String color = "White";
    private boolean filled = false;
    
    public GeometricObject() {
    }
    
    // Constructor Overloading
    public GeometricObject(String c, boolean f) {
    	this.color = c;
        this.filled = f;
    }
    
    // General Method
    public void setColor(String c) {
    	this.color = c;
    }
    
    public void setFilled(boolean f) {
    	this.filled = f;
    }
}
  • Subclass
    디테일한 하위 클래스
// Circle Is-A GeometricObject
public class Circle extends GeometricObject {
	private double radius;
    
    public Circle() {
    	this(1.0);
    }
    // Constructor Overloading
    public Circle(double r) {
    	this.radius = r;
    }
    // Constructor Overloading
    public Circle(double r, String c, boolean f) {
    	this.radius = r;
        // Using method of superclass
        setColor(c);
        setFilled(f);
    }
    
    // Detail Method
    public double getRadius() {
    	return radius;
    }
    
    public double getArea() {
    	return radius*radius*Math.PI;
    }
}
  • Inheritance 생성자 연쇄 호출 예제
    자식 클래스 생성자는 부모 클래스 생성자를 먼저 호출해야 한다!
class Person { // general class
	public Person() { System.out.println("(1) Performs person's Tasks"); }
}

class Employee extends Person { // subclass of Person
	public Employee() {
    	// 생성자 오버로딩
    	this("(2) Invoke Employee's overloaded constructor");
        System.out.println("(3)");
    }

	public Employee(String s) { System.out.println(s); }
}

// subclass of Employee
public class Faculty extends Employee {
	public Faculty() { System.out.println("(4)"); }
    public static void main(String[] args) {
    	new Faculty();
    }
}
<출력>
(1) Performs person's Tasks
(2) Invoke Employee's overloaded constructor
(3)
(4)
  • Overloading vs Overriding
    Overloading: 같은 클래스에서 이름은 같지만 인자가 다른 함수를 가지는 것
    Overrriding: 서브클래스에서 부모클래스에 정의된 메소드를 특별하게 구현하는 것

<참고자료>
탁성우, "플랫폼기반프로그래밍", 부산대학교

0개의 댓글