- Java 세팅 및 실습은 Windows 환경에서 IntelliJ를 통해 진행되었습니다.
3. 패키지와 클래스 활용법: 생성자와 상속
- Java에서 패키지는 클래스와 인터페이스를 묶는 컨테이너 역할을 하며, 클래스는 객체를 생성하고 행동을 정의하는 설계도입니다.
- 이 섹션에서는 패키지와 클래스의 활용법(특히 생성자와 상속)에 대해 설명하겠습니다.
3-1. 패키지 (Package)
- 패키지는 관련된 클래스와 인터페이스를 그룹화하여 구조적으로 관리하는 데 사용됩니다.
- 패키지를 사용하면 네임스페이스 충돌을 방지하고, 코드의 재사용성과 유지보수성을 높일 수 있습니다.
패키지 선언
- 패키지는 소스 파일의 맨 위에서 선언하며, 패키지 이름은 일반적으로 회사 도메인 이름을 역순으로 하여 고유성을 확보합니다.
- 관례이긴하지만, 공개적으로 코드를 배포할때는 꼭 숙지해 두시는것이 좋습니다.
package com.example.myapp;
- 위의 예제에서 com.example.myapp은 패키지 이름입니다. 해당 패키지에 포함된 모든 클래스는 이 패키지 내에서 관리됩니다.
- 패키지명은 모두 소문자로 나타내야합니다. (관례)
a.b.c
라는 패키지와 a.b
라는 패키지가 있을때 a.b
와 a.b.c
는 관계가 있어보이지만, 전혀 다른 패키지로 인식되어 동작한다는 점도 알아주시는게 좋습니다.
패키지 사용
- 다른 패키지에 있는 클래스를 사용하려면
import
문을 사용하여 해당 클래스를 가져와야 합니다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
}
}
java.util.Scanner
는 Java의 표준 라이브러리 패키지 중 하나입니다. import
를 사용하면 클래스 이름을 직접 사용할 수 있습니다.
- 참고로 불러온 패키지들의 이름이 겹치는 경우, 하나만 선택하여 import하고 다른 패키지는 경로를 모두 입력해주셔야합니다.
3-2. 클래스 활용: 생성자(Constructor)
- 생성자는 객체가 생성될 때 호출되는 특수한 메서드로, 객체의 초기화에 사용됩니다.
- 생성자는 클래스 이름과 동일하며, 반환 타입이 없습니다.
기본 생성자
- 기본 생성자는 매개변수가 없는 생성자입니다. 클래스에 생성자가 정의되지 않으면, Java 컴파일러가 자동으로 기본 생성자를 생성합니다.
public class Person {
String name;
int age;
public Person() {
name = "Unknown";
age = 0;
}
public void introduce() {
System.out.println("My name is " + name + " and I am " + age + " years old.");
}
}
매개변수가 있는 생성자
- 매개변수가 있는 생성자는 객체 생성 시 초기 값을 설정할 수 있도록 합니다.
public class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void introduce() {
System.out.println("My name is " + name + " and I am " + age + " years old.");
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
person.introduce();
}
}
생성자 오버로딩
- 생성자 오버로딩은 클래스 내에서 여러 개의 생성자를 정의하는 것을 말합니다.
- 생성자마다 다른 매개변수를 가질 수 있습니다.
public class Person {
String name;
int age;
public Person() {
this.name = "Unknown";
this.age = 0;
}
public Person(String name) {
this.name = name;
this.age = 0;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void introduce() {
System.out.println("My name is " + name + " and I am " + age + " years old.");
}
}
3-3. 클래스 활용: 상속
- 상속은 객체지향 프로그래밍의 핵심 개념으로, 기존 클래스(부모 클래스)의 속성과 메서드를 새로운 클래스(자식 클래스)가 물려받아 사용하는 기능입니다.
- 이를 통해 코드의 재사용성과 확장성을 높일 수 있습니다.
- 다형성에 대해 다룰 때 다시 상세히 다룰 예정입니다.
3-3-1.기본적인 상속
- 상속은
extends
키워드를 사용하여 구현됩니다.
public class Animal {
String name;
public void eat() {
System.out.println(name + " is eating.");
}
}
public class Dog extends Animal {
public void bark() {
System.out.println(name + " is barking.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "Buddy";
dog.eat();
dog.bark();
}
}
- 위의 예시에서 Dog 클래스는 Animal 클래스를 상속받아 eat() 메서드를 사용할 수 있습니다. 또한 Dog 클래스는 자신만의 메서드 bark()를 추가로 정의할 수 있습니다.
3-3-2. 메서드 오버라이딩
- 메서드 오버라이딩은 부모 클래스에서 상속받은 메서드를 자식 클래스에서 재정의하는 것입니다.
- 오버라이딩을 통해 자식 클래스는 부모 클래스의 메서드를 자신의 방식으로 구현할 수 있습니다.
- 다형성에 대해서 다룰때 다시 자세히 다룰 예정입니다.
public class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal();
Animal myDog = new Dog();
myAnimal.sound();
myDog.sound();
}
}
- 참고로 메서드 위에
@Override
를 안 붙여도 동작은 하는데 가능한 붙여주시는 것이 좋습니다. 오버라이딩시 실수에 의한 에러를 방지할 수 있고 가독성도 높일 수 있기 때문입니다.
3-3-3. super 키워드
super
키워드는 자식 클래스에서 부모 클래스의 메서드나 생성자를 호출할 때 사용됩니다. (물론 변수를 불러오는데에도 쓰입니다.)
public class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void sound() {
System.out.println(name + " makes a sound");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void sound() {
super.sound();
System.out.println(name + " barks");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.sound();
}
}
- 위 예시에서 Dog 클래스는 부모 클래스의 생성자와 메서드를
super
키워드를 사용하여 호출합니다.
마무리
- 패키지와 클래스를 잘 활용하면 Java 프로그램의 구조를 더 잘 조직화하고, 유지보수성을 높일 수 있습니다.
- 생성자는 객체 초기화 시 필수적인 역할을 하며, 상속은 코드 재사용성을 높이고 객체지향의 중요한 원칙을 구현하는 데 중요한 기능입니다.
- 상속을 통해 기존 클래스를 확장하고, 메서드 오버라이딩과 super 키워드를 사용하여 더 강력하고 유연한 클래스를 설계할 수 있습니다.
- 다음 포스팅에서는 자바의 제어자에 대해서 먼저 정리할 예정입니다.