클래스 (Class): 객체를 만들어내기 위한 일종의 틀이며, 객체가 가져야 할 속성과 메서드를 정의한 것
→ 객체를 위한 설계도
객체: 클래스로부터 만들어지는 실체, 클래스 타입으로 선언된 변수
인스턴스: 객체가 메모리에 할당이 된 상태이며 런타임에 구동되는 객체
// class
public class Person {
// attribute
String name;
int IQ;
int str;
// constructor
public Person(String name, int IQ, int str){
this.name = name;
this.IQ = IQ;
this.str = str;
}
public Person(){
this.name = "TEST1";
this.IQ = 100;
this.str = 100;
}
// method
public void levelup() {
this.IQ = this.IQ + 1;
this.str = this.str + 1;
}
public static void main(String[] args) {
Person a = new Person(); // 객체 >> 인스턴스
a.levelup();
Person b; // 객체
b = new Person("TEST2", 1, 1000); // 인스턴스
b.levelup();
}
}
static 키워드를 사용하면 해당 메서드 또는 속성이 클래스 자체에 속하며, 객체 인스턴스와는 관련이 없는 클래스 레벨의 변수와 메서드로 사용된다.
장점
- 클래스 내에서 공통 기능을 구현하고 중복을 줄일 수 있다.
- 해당 클래스로 만들어지는 객체 간에 메서드와 변수를 공유할 수 있습니다.
- 코드의 명시성이 향상되어 해당 메서드나 속성이 클래스의 일부임을 분명하게 나타냄으로써 코드의 가독성과 유지 보수성을 향상시킨다.
- 자바에서 static 키워드로 선언된 변수, 메서드 등은 선언과 동시에 Method Area 메모리 영역에 할당된다.
해당 영역에 할당되면 프로그램이 종료될 때까지 Garbage Collector에 의해 회수되지 않는다.
따라서, 클래스가 객체로 사용되지 않는 경우, 메모리 낭비를 초래할 수 있다.
public class Person {
String name;
int IQ;
int str;
public Person(String name, int IQ, int str){
this.name = name;
this.IQ = IQ;
this.str = str;
}
public Person(){
this.name = "test1";
this.IQ = 100;
this.str = 100;
}
public void levelup(){
this.IQ = this.IQ + 1;
this.str = this.str + 1;
}
// public void talk(Person a, Person b){
// System.out.println("test");
// }
private static void talk(Person a, Person b){
System.out.println("test);
}
public static void main(String[] args) {
Person a = new Person();
a.levelup();
Person b;
b = new Person("test2", 1000, 1);
b.levelup();
Person.talk(a, b); //static method 사용
System.out.println(Person.GUDOC);
}
}
- 장점
- 다양한 상황에서 적합한 메서드를 선택하여 사용할 수 있으며, 이는 프로그램의 다양한 요구사항을 처리하는 데 도움 될 수 있다.
- 프로그램의 유연성을 높이고 코드를 깔끔하게 하는 효과가있다.
class Calculator{
void multiply(int a, int b) {
System.out.println("결과는 : "+(a * b) + "입니다.");
}
void multiply(int a, int b,int c) {
System.out.println("결과는 : "+(a * b * c) + "입니다.");
}
void multiply(double a, double b) {
System.out.println("결과는 : "+(a * b) + "입니다.");
}
}
public class MyClass {
public static void main(String args[]) {
int a = 1;
int b = 2;
int d = 4;
Calculator c = new Calculator();
c.multiply(a, b);
c.multiply(a, b, d);
double aa = 1.2;
double bb = 1.4;
c.multiply(aa, bb);
}
}
using namespace std;
string a = "aaa";
string b = string("aaa");
string c = string(3, 'a');
//c++에서도 오버로딩이 적용되고 있다.
- 장점
- 다형성 구현 (Polymorphism): 오버라이딩을 통해 상위 클래스에서 정의된 메서드를 하위 클래스에서 다양하게 구현할 수 있다.
→ 동일한 메서드 호출로 다양한 동작을 수행할 수 있음을 의미- 재사용성: 상위 클래스에서 구현된 공통 동작을 하위 클래스에서 재사용할 수 있다
→ 이로써 중복 코드를 피하고 코드 재사용성을 높일 수 있음- 유지 보수성: 코드를 유지 관리할 때 상위 클래스의 메서드를 수정하면 모든 하위 클래스에서 자동으로 변경이 반영되므로 유지 보수성을 향상시킬 수 있다.
- static으로 선언된 메서드나 final로 선언된 메서드는 오버라이딩이 불가능하다.
abstract class Animal {
void eat() {
System.out.println("먹습니다.");
}
}
class Person extends Animal {
@Override
void eat() {
System.out.println("사람처럼 먹습니다.");
}
}
자바는 클래스 단일 상속만을 지원하기 때문에 복잡성과 충돌 등의 다중 상속 문제가 발생하지 않는다.
- 자바에서는 이러한 문제를 해결하기 위해 인터페이스(Interface)를 제공한다.
인터페이스는 클래스가 구현해야 하는 메서드의 명세를 정의하며, 한 클래스는 여러 인터페이스를 구현할 수 있습니다.
이를 통해 다중 상속으로 인한 복잡성을 피하면서 유연성을 확보할 수 있다.
인터페이스로부터 메서드를 오버라이딩하는 것이 아니라 구현(implementing)한다고 표현한다.
- 오버라이딩은 상위 클래스의 메서드를 하위 클래스에서 다시 정의하는 것을 의미하지만, 인터페이스는 메서드의 구현 내용을 가지지 않으므로 구현이라고 표현한다.
추상화(Abstraction): 복잡한 데이터, 구조, 시스템 등에서 핵심적인 부분을 간추려 내거나 세부사항을 숨기고 인터페이스를 만들어 복잡성을 줄이는 과정이다.
데이터 추상화: 어떠한 데이터들의 공통점을 모으고 차이점은 버린다.
- 고양이, 강아지, 원숭이 등의 객체들의 공통적인 특징을 묶어 동물이라는 카테고리로 카테고리화 시킨다.
- 각각의 울음소리 등 세부적인 특징은 구현 계층에서 재정의할 수 있다.
프로세스 추상화: 내부 프로세스를 숨기고 외부에서 사용자에게 간단한 인터페이스를 제공하는 것을 의미한다.
- 데이터베이스가 어떻게 데이터를 저장하는지는 모르지만 단순하게 insert, update 등의 쿼리로 데이터를 저장할 수 있다.
abstract class Animal {
public abstract void animalSound();
public void sleep() {
System.out.println("zzz");
}
}
class Pig extends Animal {
public void animalSound() {
System.out.println("꿀꿀꿀~");
}
}
class Dog extends Animal {
public void animalSound() {
System.out.println("왈왈~");
}
@Override
public void sleep() {
System.out.println("ggg");
}
}