[JAVA] (14)

안녕하세요! 자바를 배우고 있는 코딩 입문자 여러분, 오늘은 자바의 'final' 키워드에 대해 쉽게 알아보려고 합니다. 자바에서 'final' 키워드는 변수, 메서드, 클래스를 수정할 수 없도록 만들어 주는 역할을 합니다. 이번 포스트에서는 이 세 가지 케이스를 각각 살펴보고, 왜 'final' 키워드를 사용하는지에 대해서 알아봅시다.

 

1. final 변수

  • final 변수는 한 번 값을 할당하면 그 이후에 값을 변경할 수 없는 변수입니다. 다른 말로 상수라고도 불립니다. final 변수는 주로 대문자와 밑줄(_)을 사용하여 이름을 지어줍니다.

예시:

1
2
final int MAX_SPEED = 100;
 
cs

 

2. final 메서드

  • final 메서드는 하위 클래스에서 오버라이딩(재정의)할 수 없는 메서드입니다. 즉, final로 선언된 메서드는 상속받은 하위 클래스에서 수정할 수 없으므로, 원래의 기능을 그대로 유지하게 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
class Animal {
  final void makeSound() {
    System.out.println("The animal makes a sound");
  }
}
 
class Dog extends Animal {
  // 아래 코드는 오류를 발생시킵니다. 상위 클래스의 makeSound() 메서드가 final로 선언되었기 때문입니다.
  void makeSound() {
    System.out.println("The dog barks");
  }
}
 
cs

 

3. final 클래스

  • final 클래스는 상속할 수 없는 클래스입니다. 다시 말해, final로 선언된 클래스는 다른 클래스가 상속받을 수 없으므로, 그대로 사용해야 합니다.

예시:

1
2
3
4
5
6
7
8
9
final class Animal {
  // 클래스 코드
}
 
// 아래 코드는 오류를 발생시킵니다. Animal 클래스가 final로 선언되었기 때문입니다.
class Dog extends Animal {
  // 클래스 코드
}
 
cs

 

자바의 'final' 키워드를 사용하는 이유는 다음과 같습니다.

  1. 불변성: final 변수를 사용하여 상수를 생성함으로써 프로그램 안에서 값이 변경되지 않도록 보장할 수 있습니다.
  2. 안전성: final 메서드와 클래스는 상속과 오버라이딩을 통한 수정을 막아, 원래의 구현을 보존할 수 있게 합니다.
  3. 유지보수: 코드의 복잡성을 줄이고, 의도하지 않은 변경으로 인한 버그 발생 가능성을 줄일 수 있습니다.

 

 

 

 

 

 

'[JAVA] > ┃ⓑ KEYWORDS' 카테고리의 다른 글

[JAVA] static  (0) 2023.03.30
[JAVA] void  (0) 2023.03.20
[JAVA] 다형성 (Polymorphism)  (0) 2023.03.19
[JAVA] 추상화 (Abstraction)  (0) 2023.03.19
[JAVA] 오버로딩(Overloading) vs 오버라이딩(Overriding)  (0) 2023.03.19

안녕하세요 여러분! 

오늘은 자바(Java)의 static 키워드에 대해 알아보겠습니다. 



1. Static 의 정의
자바에서 static 키워드는 변수와 메소드에 사용되며, 객체를 생성하지 않고도 사용할 수 있는 변수와 메소드를 의미합니다. 즉, 클래스를 통해 직접 접근할 수 있는 멤버들입니다.

2. Static 변수
Static 변수는 클래스 변수라고도 부릅니다. 

클래스 내에서 선언되고 static 키워드를 사용하여 정의됩니다. 

static 변수는 클래스당 하나만 존재하며, 모든 객체가 공유하는 변수입니다.

예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Car {
    static int numberOfCars = 0;
    
    Car() {
        numberOfCars++;
    }
}
 
public class Main {
    public static void main(String[] args) {
        Car car1 = new Car();
        Car car2 = new Car();
        Car car3 = new Car();
        
        System.out.println("생성된 자동차의 수: " + Car.numberOfCars);
    }
}
 
cs
위의 예제에서는 Car 클래스에 static 변수 numberOfCars를 선언했습니다. 자동차 객체를 생성할 때마다 생성자에서 numberOfCars를 증가시키며, 생성된 자동차의 수를 출력합니다.

 

3.Static 메소드

Static 메소드는 클래스 메소드라고도 부릅니다.

static 메소드는 객체를 생성하지 않고도 호출할 수 있는 메소드입니다.

주로 유틸리티 함수나 객체 생성 없이도 동작하는 메소드에 사용됩니다.

 

예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MathUtil {
    static int add(int a, int b) {
        return a + b;
    }
    
    static int subtract(int a, int b) {
        return a - b;
    }
}
 
public class Main {
    public static void main(String[] args) {
        int result1 = MathUtil.add(53);
        int result2 = MathUtil.subtract(72);
        
        System.out.println("5 + 3 = " + result1);
        System.out.println("7 - 2 = " + result2);
    }
}
 
cs
위의 예제에서는 MathUtil 클래스에 두 개의 static 메소드인 add와 subtract를 선언했습니다. 객체를 생성하지 않고도 메소드를 호출하여 덧셈과 뺄셈 결과를 출력할 수 있습니다.

 

 

4.주의사항

  • Static 변수는 모든 객체가 공유하기 때문에, 값을 수정하면 모든 객체에서 수정된 값을 참조하게 됩니다.
  • Static 메소드에서는 static이 아닌 멤버에 직접 접근할 수 없습니다.

 

5.Static 블록

Static 블록은 클래스가 로드될 때 한 번만 실행되는 특별한 블록입니다.

주로 static 변수를 초기화하는 데 사용됩니다.

 

예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyStaticBlock {
    static int[] numbers;
 
    static {
        numbers = new int[10];
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = i * 2;
        }
    }
}
 
public class Main {
    public static void main(String[] args) {
        for (int number : MyStaticBlock.numbers) {
            System.out.println("Number: " + number);
        }
    }
}
 
cs

위의 예제에서는 MyStaticBlock 클래스에 static 블록을 사용하여 numbers 배열을 초기화했습니다. 이 배열은 클래스가 로드될 때 한 번만 초기화되고, main 메소드에서 배열의 값을 출력할 수 있습니다.

 

 

6. Static과 객체지향 프로그래밍

Static을 사용하면 객체 생성 없이도 변수와 메소드에 접근할 수 있지만, 객체지향 프로그래밍의 원칙과 다소 상반될 수 있습니다.

객체지향 프로그래밍은 객체 간의 상호작용을 통해 문제를 해결하는 것을 목표로 하는데, static은 객체 간의 상호작용이 아닌 클래스 단위로 접근하기 때문입니다.

따라서, 상황에 맞게 적절히 사용해야 합니다.

 

정리

  • Static 키워드는 변수와 메소드, 블록에 사용할 수 있습니다.
  • Static 변수는 클래스 당 하나만 존재하며 모든 객체가 공유합니다.
  • Static 메소드는 객체 생성 없이 호출할 수 있습니다.
  • Static 블록은 클래스가 로드될 때 한 번만 실행되며 주로 초기화 작업에 사용됩니다.
  • Static은 객체지향 프로그래밍의 원칙과 다소 상반되는 개념이므로 적절한 상황에서 사용해야 합니다.

이 글을 통해 자바에서의 static 키워드에 대해 알아보았습니다.

 

여러분의 코딩 공부에 도움이 되길 바랍니다!

'[JAVA] > ┃ⓑ KEYWORDS' 카테고리의 다른 글

[JAVA] final  (0) 2023.03.30
[JAVA] void  (0) 2023.03.20
[JAVA] 다형성 (Polymorphism)  (0) 2023.03.19
[JAVA] 추상화 (Abstraction)  (0) 2023.03.19
[JAVA] 오버로딩(Overloading) vs 오버라이딩(Overriding)  (0) 2023.03.19

자바에서 void는 특수한 키워드로, 메소드가 값을 반환하지 않는다는 것을 나타냅니다. 메소드는 일련의 작업을 수행하거나 객체를 조작하는 데 사용되며, 경우에 따라 반환할 값이 없을 수 있습니다. 이 경우 메소드의 반환 타입으로 void를 사용합니다.

예를 들어, 다음 코드에서는 printGreeting 메소드가 void로 선언되어 있습니다. 

이 메소드는 값을 반환하지 않으며, 대신 콘솔에 "Hello, world!"라는 문구를 출력합니다.

1
2
3
4
5
6
7
8
9
10
public class HelloWorld {
    public static void main(String[] args) {
        printGreeting();
    }
 
    public static void printGreeting() {
        System.out.println("Hello, world!");
    }
}
 
cs

위 예제에서, printGreeting 메소드는 콘솔에 문구를 출력하는 것이 전부이므로 반환할 값이 없습니다. 

따라서 반환 타입으로 void를 사용합니다.

void가 아닌 반환 타입을 가진 메소드의 경우, 메소드가 실행을 완료하면 호출한 쪽으로 값을 반환해야 합니다.

 이 반환 값은 메소드의 반환 타입과 일치해야 합니다. 

이렇게 반환되는 값은 변수에 저장할 수도 있고, 다른 메소드에 전달할 수도 있습니다.

결론적으로, void는 메소드가 값을 반환하지 않는다는 것을 나타내는 키워드로 이해하면 됩니다. 

메소드의 작업이 반환할 값이 필요하지 않거나 결과를 다른 방식으로 처리할 때 사용합니다.

'[JAVA] > ┃ⓑ KEYWORDS' 카테고리의 다른 글

[JAVA] final  (0) 2023.03.30
[JAVA] static  (0) 2023.03.30
[JAVA] 다형성 (Polymorphism)  (0) 2023.03.19
[JAVA] 추상화 (Abstraction)  (0) 2023.03.19
[JAVA] 오버로딩(Overloading) vs 오버라이딩(Overriding)  (0) 2023.03.19

안녕하세요! 오늘은 자바 프로그래밍의 핵심 개념 중 하나인 '다형성(Polymorphism)'에 대해 알아보겠습니다. 

다형성은 객체지향 프로그래밍에서 상속과 함께 사용되며, 하나의 인터페이스로 여러 가지 구현을 사용할 수 있게 해줍니다. 

이를 통해 코드의 유연성과 확장성이 높아집니다. 

예시와 주석을 통해 다형성을 자세하게 알아봅시다.

예시: 동물 클래스를 상속받은 고양이와 개 클래스

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
public abstract class Animal {
    abstract void makeSound();
}
 
public class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("고양이가 냥냥거린다.");
    }
}
 
public class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("개가 멍멍 짖는다.");
    }
}
 
public class Main {
    public static void main(String[] args) {
        // 다형성을 사용하여 상위 타입의 변수로 하위 타입의 객체를 참조
        Animal myAnimal = new Cat();
        myAnimal.makeSound(); // 고양이가 냥냥거린다.
 
        myAnimal = new Dog();
        myAnimal.makeSound(); // 개가 멍멍 짖는다.
    }
}
 
cs
이 예제에서는 Animal이라는 추상 클래스를 선언하고, 추상 메소드 makeSound()를 정의했습니다. Cat과 Dog 클래스는 Animal 클래스를 상속받아 makeSound() 메소드를 오버라이딩하여 각각 고양이와 개의 소리를 출력하는 구현을 제공합니다.
다형성을 사용하는 부분은 main() 메소드에서 확인할 수 있습니다. Animal 타입의 변수 myAnimal은 Cat 인스턴스와 Dog 인스턴스를 참조할 수 있습니다. 이를 통해 makeSound() 메소드를 호출하면, 참조하는 인스턴스에 따라 다른 결과를 출력합니다.
이 예제를 통해 다형성의 장점을 확인할 수 있습니다. 하나의 상위 타입 변수로 여러 하위 타입 객체를 참조할 수 있으며, 동일한 메소드 호출로 다양한 구현을 실행할 수 있습니다. 이를 통해 코드의 유연성과 확장성이 향상되며, 유지 관리가 용이해집니다.

 

이어서 다형성의 사용에 대해 더 알아봅시다.

 다형성은 인터페이스를 사용할 때도 유용합니다. 

인터페이스를 구현하는 여러 클래스를 동일한 인터페이스 타입 변수로 참조할 수 있기 때문입니다. 

이를 통해 다양한 구현을 쉽게 교체할 수 있습니다.

예시: 동물 인터페이스와 구현하는 포유류, 조류 클래스

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
public interface Animal {
    void makeSound();
}
 
public class Mammal implements Animal {
    @Override
    public void makeSound() {
        System.out.println("포유류가 소리를 낸다.");
    }
}
 
public class Bird implements Animal {
    @Override
    public void makeSound() {
        System.out.println("조류가 소리를 낸다.");
    }
}
 
public class Main {
    public static void main(String[] args) {
        // 다형성을 사용하여 인터페이스 타입의 변수로 구현체를 참조
        Animal myAnimal = new Mammal();
        myAnimal.makeSound(); // 포유류가 소리를 낸다.
 
        myAnimal = new Bird();
        myAnimal.makeSound(); // 조류가 소리를 낸다.
    }
}
 
cs
위 예제에서는 Animal 인터페이스를 선언하고, makeSound() 메소드를 정의했습니다. Mammal과 Bird 클래스는 Animal 인터페이스를 구현하여 각각 포유류와 조류의 소리를 출력하는 구현을 제공합니다.

main() 메소드에서는 인터페이스 타입의 변수 myAnimal로 Mammal 인스턴스와 Bird 인스턴스를 참조할 수 있습니다. 이를 통해 makeSound() 메소드를 호출하면, 참조하는 인스턴스에 따라 다른 결과를 출력합니다.

이 예제를 통해 인터페이스를 사용하는 다형성의 장점을 확인할 수 있습니다. 다형성을 통해 인터페이스를 구현하는 다양한 클래스를 동일한 인터페이스 타입 변수로 참조할 수 있으며, 동일한 메소드 호출로 다양한 구현을 실행할 수 있습니다. 이를 통해 코드의 유연성과 확장성이 향상되며, 유지 관리가 용이해집니다.

 

다형성은 객체지향 프로그래밍에서 꼭 알아야 할 중요한 개념입니다. 

이를 이해하고 코드에 적용하면, 프로그램의 구조가 간결해지고 유연성과 확장성이 향상되어 효율적인 개발이 가능해집니다.

'[JAVA] > ┃ⓑ KEYWORDS' 카테고리의 다른 글

[JAVA] static  (0) 2023.03.30
[JAVA] void  (0) 2023.03.20
[JAVA] 추상화 (Abstraction)  (0) 2023.03.19
[JAVA] 오버로딩(Overloading) vs 오버라이딩(Overriding)  (0) 2023.03.19
[JAVA] 상속 (Inheritance)  (0) 2023.03.19

안녕하세요! 오늘은 자바 프로그래밍에서 중요한 개념인 '추상화(Abstraction)'에 대해 알아보겠습니다. 

추상화는 복잡한 시스템을 간단한 개념으로 표현하는 프로그래밍 기법입니다. 

클래스와 인터페이스를 사용해 프로그램의 복잡성을 줄이고 유지 관리를 용이하게 하는 데 도움이 됩니다. 

예시를 통해 추상화를 자세하게 알아봅시다.

1. 추상 클래스(Abstract Class)
추상 클래스는 하나 이상의 추상 메소드를 포함하는 클래스입니다.

추상 메소드는 선언만 있고 구현이 없는 메소드이며, 하위 클래스에서 반드시 오버라이딩해야 합니다.

추상 클래스는 인스턴스를 생성할 수 없으며, 상속을 통해 사용할 수 있습니다.

예시: 도형 클래스와 상속을 사용한 삼각형, 사각형 클래스 구현하기

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
32
33
34
public abstract class Shape {
    abstract double getArea();
}
 
public class Triangle extends Shape {
    private double base;
    private double height;
 
    public Triangle(double base, double height) {
        this.base = base;
        this.height = height;
    }
 
    @Override
    double getArea() {
        return (base * height) / 2;
    }
}
 
public class Rectangle extends Shape {
    private double width;
    private double height;
 
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
 
    @Override
    double getArea() {
        return width * height;
    }
}
 
cs

 

이 예제에서는 추상 클래스인 Shape를 선언하고, 추상 메소드 getArea()를 정의했습니다. Shape 클래스를 상속받는 Triangle과 Rectangle 클래스는 getArea() 메소드를 각각 오버라이딩하여 삼각형과 사각형의 넓이를 계산하는 구현을 제공합니다.

이렇게 추상 클래스를 사용하면 도형의 공통 특성을 Shape 클래스에 정의할 수 있고, 각 도형의 세부 구현은 하위 클래스에 나누어 관리할 수 있습니다. 이를 통해 코드의 구조를 간결하게 만들고 유지 관리가 용이해집니다.

 

2. 인터페이스(Interface)

인터페이스는 모든 메소드가 추상 메소드인 경우 사용할 수 있는 개념입니다.

인터페이스는 다중 상속을 지원하며, 다양한 구현을 강제하거나 규약을 정의하는 데 사용됩니다.

 

예시: 동물 클래스와 인터페이스를 사용한 포유류, 조류 클래스 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface Animal {
    void makeSound();
}
 
public class Mammal implements Animal {
    @Override
    public void makeSound() {
        System.out.println("포유류가 소리를 낸다.");
    }
}
 
public class Bird implements Animal {
    @Override
    public void makeSound() {
        System.out.println("조류가 소리를 낸다.");
    }
}
 
cs

 

이 예제에서는 인터페이스인 Animal을 선언하고, 추상 메소드 makeSound()를 정의했습니다. Animal 인터페이스를 구현하는 Mammal과 Bird 클래스는 makeSound() 메소드를 오버라이딩하여 포유류와 조류의 소리를 출력하는 구현을 제공합니다.

이렇게 인터페이스를 사용하면 다양한 동물들의 공통 특성을 Animal 인터페이스에 정의할 수 있고, 각 동물의 세부 구현은 해당 클래스에 나누어 관리할 수 있습니다.

또한, 인터페이스를 사용하면 다중 상속을 지원하여 여러 인터페이스를 동시에 구현할 수 있습니다.

이를 통해 코드의 확장성과 유연성이 높아집니다.

 

추상화를 사용하면 코드의 복잡성을 줄이고 유지 관리가 쉬운 프로그램을 작성할 수 있습니다.

추상 클래스와 인터페이스를 활용하여 공통된 기능을 재사용하고, 확장성과 유연성을 높여보세요!

'[JAVA] > ┃ⓑ KEYWORDS' 카테고리의 다른 글

[JAVA] void  (0) 2023.03.20
[JAVA] 다형성 (Polymorphism)  (0) 2023.03.19
[JAVA] 오버로딩(Overloading) vs 오버라이딩(Overriding)  (0) 2023.03.19
[JAVA] 상속 (Inheritance)  (0) 2023.03.19
[JAVA] 캡슐화(Encapsulation)  (0) 2023.03.18

안녕하세요 여러분! 

오늘은 자바 프로그래밍에서 중요한 개념인 '오버로딩(Overloading)'과 '오버라이딩(Overriding)'의 차이점에 대해 쉽게 설명해드리려고 합니다. 

두 개념은 함수를 다룰 때 자주 사용되며, 이들을 이해하고 활용할 줄 알면 자바 프로그래밍에 큰 도움이 됩니다. 

그럼 시작해볼까요?

 

오버로딩(Overloading)
오버로딩은 하나의 클래스 내에서 같은 이름의 메소드를 여러 개 가질 수 있게 하는 것입니다. 

오버로딩된 메소드들은 매개변수의 타입, 개수, 순서가 다르게 정의됩니다. 

이를 통해 개발자들은 메소드를 더 유연하게 사용할 수 있게 됩니다.

 

예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Calculator {
    int add(int a, int b) {
        return a + b;
    }
 
    double add(double a, double b) {
        return a + b;
    }
 
    int add(int a, int b, int c) {
        return a + b + c;
    }
}
cs
위 예시에서는 Calculator 클래스에 add 메소드를 오버로딩하였습니다. 각 메소드는 다른 타입 혹은 개수의 인수를 받아 처리할 수 있습니다.

 

오버라이딩(Overriding)
오버라이딩은 상속 관계에 있는 자식 클래스가 부모 클래스의 메소드를 재정의하는 것을 말합니다. 

오버라이딩을 통해 자식 클래스는 부모 클래스의 메소드를 덮어쓰거나 확장할 수 있습니다. 

이를 통해 코드 재사용성과 유연성이 증가합니다.

예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Animal {
    void speak() {
        System.out.println("동물이 소리를 냅니다.");
    }
}
 
class Dog extends Animal {
    @Override
    void speak() {
        System.out.println("멍멍!");
    }
}
 
class Cat extends Animal {
    @Override
    void speak() {
        System.out.println("야옹!");
    }
}
cs
위 예시에서는 Animal 클래스를 상속받은 Dog와 Cat 클래스가 부모 클래스의 speak() 메소드를 오버라이딩하여 각자 고유의 동작을 구현하고 있습니다.

 

정리

  • 목적: 오버로딩은 하나의 클래스에서 다양한 인수를 받을 수 있는 메소드를 정의하는 것이 목적입니다. 반면, 오버라이딩은 상속받은 메소드를 자식 클래스에 맞게 수정하거나 확장하는 것이 목적입니다.
  • 범위: 오버로딩은 같은 클래스 내에서 발생하며, 오버라이딩은 상속 관계에 있는 부모 클래스와 자식 클래스 사이에서 발생합니다.
  • 메소드명: 오버로딩된 메소드들은 같은 이름을 가지지만, 매개변수의 타입, 개수, 순서가 다릅니다. 오버라이딩된 메소드는 부모 클래스와 자식 클래스에서 동일한 메소드 서명을 가져야 합니다.
  • 키워드: 오버라이딩된 메소드에는 @Override 어노테이션을 붙여서 컴파일러에게 해당 메소드가 부모 클래스의 메소드를 재정의하고 있음을 알려줍니다. 오버로딩에서는 이와 같은 키워드가 필요하지 않습니다.

 

여러분이 이 글을 통해 자바의 오버로딩과 오버라이딩 개념에 대해 쉽게 이해할 수 있기를 바랍니다.

이 두 기법을 활용하면 코드의 유연성과 재사용성이 크게 향상되므로, 자바 프로그래밍에 있어 중요한 개념입니다.

'[JAVA] > ┃ⓑ KEYWORDS' 카테고리의 다른 글

[JAVA] 다형성 (Polymorphism)  (0) 2023.03.19
[JAVA] 추상화 (Abstraction)  (0) 2023.03.19
[JAVA] 상속 (Inheritance)  (0) 2023.03.19
[JAVA] 캡슐화(Encapsulation)  (0) 2023.03.18
[JAVA] this  (0) 2023.03.18

안녕하세요! 오늘은 자바 프로그래밍에서 중요한 개념인 '상속'에 대해 알아보겠습니다. 

상속은 객체 지향 프로그래밍의 핵심 원칙 중 하나로, 기존 클래스의 속성과 메소드를 새로운 클래스에 전달하는 것을 말합니다. 

이를 통해 코드의 중복을 줄이고 재사용성을 높일 수 있습니다. 

실생활 예시를 통해 상속을 자세하고 쉽게 이해해봅시다.

1. 상속이란 무엇인가?
상속은 기존 클래스를 확장하여 새로운 클래스를 생성하는 기법입니다. 

새로운 클래스는 기존 클래스의 속성과 메소드를 물려받아 사용할 수 있으며, 필요한 경우 추가 속성과 메소드를 정의할 수 있습니다. 

이를 통해 코드 중복을 줄이고, 클래스 간 관계를 명확히 할 수 있습니다.

예시: 동물 클래스와 상속을 사용한 포유류, 조류 클래스 구현하기

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
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Animal {
    String name;
    int age;
 
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    public void introduce() {
        System.out.println("이 동물의 이름은 " + name + "이고, 나이는 " + age + "입니다.");
    }
}
 
public class Mammal extends Animal {
    String furColor;
 
    public Mammal(String name, int age, String furColor) {
        super(name, age); //부모클래스의 생성자 호출
        this.furColor = furColor;
    }
 
    public void showFurColor() {
        System.out.println("이 포유류의 털 색깔은 " + furColor + "입니다.");
    }
}
 
public class Bird extends Animal {
    boolean canFly;
 
    public Bird(String name, int age, boolean canFly) {
        super(name, age); // 부모 클래스의 생성자 호출
        this.canFly = canFly;
    }
 
    public void showFlyingAbility() {
        if (canFly) {
            System.out.println("이 조류는 날 수 있습니다.");
        } else {
            System.out.println("이 조류는 날 수 없습니다.");
        }
    }
}
 
cs
위의 예시에서는 동물을 나타내는 Animal 클래스를 생성하고, 상속을 사용하여 포유류(Mammal)와 조류(Bird) 클래스를 구현했습니다. 이때, Mammal과 Bird 클래스는 Animal 클래스의 속성(name, age)과 메소드(introduce)를 상속받았으며, 각각의 고유한 속성(furColor, canFly)과 메소드(showFurColor, showFlyingAbility)를 추가로 정의했습니다.
또한 Mammal과 Bird 클래스의 생성자에서 'super()' 키워드를 사용해 부모 클래스인 Animal의 생성자를 호출했습니다. 이를 통해 부모 클래스의 속성을 초기화할 수 있습니다.

 

2. 상속 사용하기
상속하려는 클래스에 'extends' 키워드를 사용하여 기존 클래스를 명시합니다.
'super()'를 사용하여 부모 클래스의 생성자를 호출할 수 있습니다. 

이를 통해 부모 클래스의 속성을 초기화할 수 있습니다.
위에서 작성한 예제를 통해 상속된 클래스를 사용하는 방법을 살펴봅시다.

1
2
3
4
5
6
7
8
9
10
11
12
public class Main {
    public static void main(String[] args) {
        Mammal mammal = new Mammal("호랑이"5"주황색");
        mammal.introduce(); // 부모 클래스인 Animal의 메소드 사용
        mammal.showFurColor(); // Mammal 클래스의 고유 메소드 사용
 
        Bird bird = new Bird("참새"2true);
        bird.introduce(); // 부모 클래스인 Animal의 메소드 사용
        bird.showFlyingAbility(); // Bird 클래스의 고유 메소드 사용
    }
}
 
cs
이 예제에서는 Mammal과 Bird 객체를 생성하고, 부모 클래스인 Animal의 메소드(introduce)와 각각의 클래스의 고유 메소드(showFurColor, showFlyingAbility)를 사용했습니다.

3. 'super' 키워드 사용하기

 

'super' 키워드는 하위 클래스에서 상위 클래스에 접근할 때 사용합니다.

 'super'를 사용하는 주요 경우는 다음과 같습니다.

 

  • 상위 클래스의 생성자를 호출하여 속성을 초기화할 때: 하위 클래스의 생성자에서 'super()'를 사용해 상위 클래스의 생성자를 호출할 수 있습니다. 이를 통해 상위 클래스의 속성 초기화를 수행할 수 있습니다.
  • 상위 클래스의 메소드를 호출할 때: 하위 클래스에서 상위 클래스의 메소드를 오버라이딩(재정의)했을 경우, 'super'를 사용해 원래의 상위 클래스 메소드를 호출할 수 있습니다.

    예시를 통해 'super' 키워드 사용법을 살펴봅시다.
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
32
33
34
35
public class Animal {
    String name;
    int age;
 
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
 
   public void introduce() {
        System.out.println("이 동물의 이름은 " + name + "이고, 나이는 " + age + "입니다.");
    }
}
 
public class Mammal extends Animal {
    String furColor;
 
    public Mammal(String name, int age, String furColor) {
        super(name, age); // 부모 클래스의 생성자 호출
        this.furColor = furColor;
    }
 
    // Mammal 클래스에서 introduce 메소드를 오버라이딩(재정의)
    @Override
    public void introduce() {
        super.introduce(); // 부모 클래스의 introduce 메소드 호출
        System.out.println("이 포유류의 털 색깔은 " + furColor + "입니다.");
    }
}
 
public class Main {
    public static void main(String[] args) {
        Mammal mammal = new Mammal("호랑이"5"주황색");
        mammal.introduce(); // 오버라이딩된 Mammal 클래스의 introduce 메소드 사용
    }
}
cs
이 예제에서는 Mammal 클래스에서 부모 클래스인 Animal의 introduce() 메소드를 오버라이딩(재정의)했습니다. 그리고 오버라이딩된 introduce() 메소드 내부에서 super.introduce()를 사용해 원래의 부모 클래스의 introduce() 메소드를 호출했습니다. 이렇게 super 키워드를 사용하면, 하위 클래스에서 상위 클래스의 메소드를 호출할 수 있습니다.

결과적으로 이 예제에서는 Mammal 객체의 introduce() 메소드를 호출하면 다음과 같은 출력을 얻을 수 있습니다.

1
2
3
이 동물의 이름은 호랑이이고, 나이는 5입니다.
이 포유류의 털 색깔은 주황색입니다.
 
cs

 

4. 상속의 장점
상속을 사용하면 다음과 같은 장점이 있습니다.

  1.  코드의 중복을 줄일 수 있습니다: 상위 클래스의 속성과 메소드를 하위 클래스에서 재사용할 수 있으므로 코드 중복을 줄일 수 있습니다.
  2.  클래스 간 관계를 명확히 할 수 있습니다: 클래스 간의 상속 관계를 통해 객체 지향 설계에서 클래스 간의 관계를 명확히 할 수 있습니다.
  3.  유지 보수가 용이합니다: 상위 클래스의 변경이 하위 클래스에 자동으로 반영되므로, 유지 보수가 용이합니다.

이상으로 자바의 상속에 대한 설명을 마칩니다. 상속은 객체 지향 프로그래밍의 핵심 원칙 중 하나이므로 이를 이해하고 활용하면 코드의 중복을 줄이고 클래스 간 관계를 명확히 할 수 있습니다. 다음에는 다양한 자바 프로그래밍 기법을 소개하겠습니다. 감사합니다!

 

 

'[JAVA] > ┃ⓑ KEYWORDS' 카테고리의 다른 글

[JAVA] 추상화 (Abstraction)  (0) 2023.03.19
[JAVA] 오버로딩(Overloading) vs 오버라이딩(Overriding)  (0) 2023.03.19
[JAVA] 캡슐화(Encapsulation)  (0) 2023.03.18
[JAVA] this  (0) 2023.03.18
[JAVA] 생성자(Constructor)  (0) 2023.03.18

안녕하세요! 오늘은 자바 프로그래밍에서 중요한 개념인 '캡슐화'에 대해 알아보겠습니다. 

캡슐화는 객체 지향 프로그래밍의 핵심 원칙 중 하나로, 데이터와 데이터를 다루는 메소드를 하나의 '캡슐'로 묶는 것을 말합니다. 이를 통해 코드의 재사용성, 유지 보수성 등을 높일 수 있습니다. 

실생활 예시를 통해 캡슐화를 자세하고 쉽게 이해해봅시다.

1. 캡슐화란 무엇인가?
캡슐화는 클래스의 속성(멤버 변수)과 행동(메소드)을 하나의 단위로 묶어 외부에서의 접근을 제한하는 것을 말합니다. 

캡슐화를 통해 클래스를 사용하는 사용자가 클래스 내부의 구현을 알 필요 없이 인터페이스만으로 클래스를 사용할 수 있게 되며, 이를 통해 코드의 재사용성과 유지 보수성을 높일 수 있습니다.

캡슐화를 구현하기 위해서는 주로 다음과 같은 방법을 사용합니다.

 

  • 접근 제어자(access modifier): 클래스의 속성과 메소드에 접근 제한을 설정하는 키워드
  • 게터(getter)와 세터(setter): 속성에 대한 외부 접근을 제어하는 메소드

예시: 은행 계좌 클래스와 캡슐화 사용하기

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
32
33
34
35
36
37
38
39
40
41
42
public class BankAccount {
    // 속성 (멤버 변수)
    private String accountNumber;
    private double balance;
 
    // 생성자
    public BankAccount(String accountNumber, double balance) {
        this.accountNumber = accountNumber;
        this.balance = balance;
    }
 
    // 게터 (getter)
    public String getAccountNumber() {
        return accountNumber;
    }
 
    public double getBalance() {
        return balance;
    }
 
    // 세터 (setter)
    public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }
 
    public void setBalance(double balance) {
        this.balance = balance;
    }
 
    // 행동 (메소드)
    public void deposit(double amount) {
        balance += amount;
    }
 
    public void withdraw(double amount) {
        if (balance >= amount) {
            balance -= amount;
        } else {
            System.out.println("Insufficient balance");
        }
    }
}
cs
위의 예시에서는 은행 계좌를 나타내는 BankAccount 클래스를 생성했습니다. 이 클래스는 계좌 번호(accountNumber)와 잔액(balance) 등의 속성을 갖고 있으며, 입금(deposit)과 출금(withdraw) 등의 행동을 정의하고 있습니다. 이 때 캡슐화를 구현하기 위해 다음과 같은 방법을 사용했습니다.
접근 제어자를 사용해 속성에 대한 접근 제한: 속성 accountNumber와 balance에 private 접근 제어자를 사용하여 외부에서 직접 접근하는 것을 막았습니다. 이를 통해 BankAccount 클래스의 내부 데이터를 보호할 수 있습니다.
게터(getter)와 세터(setter)를 사용해 속성에 대한 외부 접근 제어: 외부에서 accountNumber와 balance에 접근하거나 수정할 수 있도록 게터와 세터 메소드를 사용했습니다. 이를 통해 클래스 사용자가 속성에 안전하게 접근할 수 있으며, 필요한 경우 로직을 변경하거나 유효성 검사를 추가할 수 있습니다.

 

이렇게 캡슐화를 적용한 BankAccount 클래스를 사용하면, 

클래스 사용자는 내부 구현에 대해 알 필요 없이 인터페이스만으로 클래스를 사용할 수 있습니다. 

 

예를 들어, 다음과 같이 BankAccount 인스턴스를 생성하고 입금, 출금 등의 작업을 수행할 수 있습니다.

1
2
3
4
5
6
7
8
public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount("123456"1000);
        account.deposit(500);
        account.withdraw(300);
        System.out.println("Account number: " + account.getAccountNumber() + ", Balance: " + account.getBalance());
    }
}
cs

 

 

이상으로 자바의 캡슐화에 대한 설명을 마칩니다. 

캡슐화는 객체 지향 프로그래밍의 핵심 원칙 중 하나이므로 이를 이해하고 활용하면 코드의 재사용성과 유지 보수성을 높일 수 있습니다.

감사합니다!

'[JAVA] > ┃ⓑ KEYWORDS' 카테고리의 다른 글

[JAVA] 오버로딩(Overloading) vs 오버라이딩(Overriding)  (0) 2023.03.19
[JAVA] 상속 (Inheritance)  (0) 2023.03.19
[JAVA] this  (0) 2023.03.18
[JAVA] 생성자(Constructor)  (0) 2023.03.18
[JAVA] 인스턴스 (Instance)  (0) 2023.03.18
1 2