Class
객체지향 프로그래밍으로 유명한 언어답게 뭔가 strict하다.
정말 간단하게 말하자면 field (js의 property), method(js의 method)로 이루어져 있다고 말할 수 있을 것 같다.
(constructor는 method니까)
public class ClassName {
// 필드 (변수)
private String name;
private int number;
// 메소드 (함수)
// 생성자 constructer-> 클래스명과 동일한 이름
// 기본생성자(defualt)는 구현하지 않더라도 자동으로 생성되서 객체를 만들어준다. => 생략 가능.
public ClassName(String name, int number) {
this.name = name;
this.number = number;
}
public void testMethod() {
System.out.println("I'm felling pretty good!");
}
@Override
// class의 최상위 클래스인 Object 클래스에 있는 toString 오버라이딩
// 원래는 클래스 이름 + hashcode로 이루어져있다.
public String toString() {
return "마이 네임: " + name + "/ 마이 넘버" + number;
}
public static void main(String[] args) {
ClassName newClass = new ClassName("지훈", 56);
System.out.println(newClass);
newClass.testMethod();
// 현재 클래스 안의 메인메소드이므로 private 접근 가능.
System.out.println(newClass.name);
}
}
constructor에 대한 부가 이해
- constructor는 그냥 함수다. 함순데 말 그대로 새로운 인스턴스를 생성해주고 그에 대한 객체 주소 (toString)을 반환해준다.
ClassName newClass = new ClassName("지훈", 56);
해당 코드의 경우에는 ClassName이라는 type의 newClass라는 변수에다가 new를 통해서 새롭게 만든 ClassName이라는 인스턴스의 주소값을 넣겠다는 뜻이다.
접근 제어자
public - 같은 프로젝트 안이면 접근 가능
protected - 같은 패키지 안이면 접근 가능, 다른 패키지라도 해당 패키지를 extends하면 사용 가능.
default - 안쓰면 이걸로 적용, 동일 패키지라면 접근 가능.
private- 클래스 내부에서만 사용 가능. (필드의 경우 private로 하고 setter와 getter를 public으로 이용하는 게 일반적)
여기서 protected가 좀 궁금해서 실험좀 해봤다.
pack3 패키지에 있는 class A
package _05_class._02_access_modifier._pack3;
public class A {
protected void method4() {}
}
pack4 패키지에 있는 class C (A클래스의 method 4 호출 가능)
package _05_class._02_access_modifier._pack4;
// A와 C는패키지가 다르므로 import 해야함.
import _05_class._02_access_modifier._pack3.A;
public class C extends A {
public static void main(String[] args) {
C c = new C();
c.method4(); // protected기 때문에 extends A이므로 호출 가능,
}
}
pack4 패키지에 있는 class D (C instance를 만들고 method4를 호출) (A 클래스의 method 4호출 불가능)
package _05_class._02_access_modifier._pack4;
public class D {
public static void main(String[] args) {
C c = new C();
c.method4(); // comfile Error
}
}
이렇게 된다.
protected는 다른 패키지라도 해당 패키지를 extends하면 사용 가능하다고 되어있고, 이는 사실이다.
다만 그 Class 안에서만 사용 가능하고 만약에 extends한 클래스를 다른 클래스에서 불러온다면 사용할 수 없는 것 같다.
(자신을 이해시키자면 extends한 클래스에서는 protected가 아닌 private이 된다고 생각하면 될 것 같다.)
그래서 조금 꼬아서 생각해봤는데 이건 된다.
pack4 패키지에 있는 class C
package _05_class._02_access_modifier._pack4;
// A와 C는패키지가 다르므로 import 해야함.
import _05_class._02_access_modifier._pack3.A;
public class C extends A {
@Override
public void method4() {
super.method4();
}
public static void main(String[] args) {
C c = new C();
c.method4(); // 당연히 호출 가능
}
}
pack4 패키지에 있는 class D
package _05_class._02_access_modifier._pack4;
public class D {
public static void main(String[] args) {
C c = new C();
c.method4(); // 호출 가능
}
}
Static (field, method)
정적 (static) 멤버
모든 인스턴스가 하나의 static 값을 공유한다고 생각하면 된다.
일반 non static의 경우 instance별로 각각의 field나 method를 가진다.
- 객체를 생성할 필요 없이 클래스 통해서 바로 접근 가능
- 클래스 메모리에 로딩되면 정적 멤버 바로 사용 가능
- 클래스 이름과 함께 dot(.) 접근법으로 사용 가능
- 정적 메소드 정적 블록은 객체가 없어도 사용 가능하므로 내부 필드와 메소드 사용 불가.
- 고로 this 키워드도 사용 불가
- but, non static method는 static method에 접근 가능함.
- 참고)
정적 필드는 객체 생성 없이도 사용 가능하므로 생성자에서 초기화 작업을 하지 않음
=> 생성자는 객체 생성 후에 실행되기 때문
정적 메소드
plus, minus 외부에서 주어진 값으로 처리하므로 정적 메서드로 처리하는 것이 유리
: 메소드에서 외부 인자를 받아서 실행하므로
Final
js의 const 와 똑같다고 생각하면 된다. 주소값이 바뀌지 않는 내에서 객체 값이 바뀌는 건 상관 없다.
다만 거기서 더 나아가서
Final method의 경우 오버라이딩을 할 수 없고
Final class의 경우 extends를 할 수 없다.
abstract Class
extends를 염두에 둔 클래스 틀이라고 생각하면 될 것 같다.
abstract를 붙이면 자식 클래스에서 따로 오버라이딩을 하거나, 그 자식 클래스에게 다시 abstract로 넘길 수 있다.
다만 abstract class의 경우 new연산자를 통해 만들 수 없다. 그냥 extends용 클래스다.
package _05_class._07_interface;
public abstract class Vehicle {
private String name;
private int maxSpeed;
public Vehicle(String name, int maxSpeed) {
this.name = name;
this.maxSpeed = maxSpeed;
}
// move abstract method로 선언
public abstract void move();
}
package _05_class._07_interface;
public class Car extends Vehicle{
public Car(String name, int maxSpeed) {
super(name, maxSpeed);
}
@Override
public void move() {
System.out.println(getName() +" 도로를 따라 이동중");
}
}
Interface
package _05_class._07_interface;
// interface 선언
public interface RemoteControl {
// 상수 필드
// - 인터페이스에 선언된 필드는 모두 ublic static final 특성을 갖는다.
// 생략하더라도 컴파일 과정에서 자동으로 붙는다.
// - 상수명은 대문자로 작성, 언더바로 연결
int MAX_VOLUME = 10;
int MIN_VOLUME = 0;
// public abstract를 안적어도 알아서 적용됨
public abstract void turnOn();
void turnOff();
// static method, field도 사용 가능.
static void kimchi() {
System.out.println("kimchi");
}
void setVolume(int volume);
}
package _05_class._07_interface;
public class RemoteControlRunner {
// interface도 하나의 타입이므로 변수의 타입으로 사용 가능
// - interface는 참조 타입 -> null 대입 가능
public static void main(String[] args) {
RemoteControl rc; // null
// rc 변수에 Tv 객체를 대입
rc = new Tv();
rc.turnOn();
RemoteControl.kimchi();
rc.setVolume(37);
rc.turnOff();
rc = new Audio();
rc.turnOn();
RemoteControl.kimchi();
rc.setVolume(-37);
rc.setVolume(3);
rc.turnOff();
}
}
abstract class VS interface
abstract class는 메소드를 바로 implement 할건지 다음 자식에게 넘겨줄건지 (또 abstract method로 할건지) 선택할 수 있지만,
interface는 전부 바로 구현해야한다. 또한 interface에서 field는 무조건 상수만 들어올 수 있다. (public final)
'포스코x코딩온' 카테고리의 다른 글
[포스코x코딩온] 풀스택 부트캠프 18주차 정리 Collection, Spring boot (0) | 2024.02.22 |
---|---|
[포스코x코딩온] 풀스택 부트캠프 18주차 정리 Java(Wrapper, generic) (0) | 2024.02.19 |
[포스코x코딩온] 풀스택 부트캠프 17주차 정리 Java(Array, Collection, Exeption) (0) | 2024.02.15 |
[포스코x코딩온] 풀스택 부트캠프 17주차 정리 Java (1) | 2024.02.13 |
3차 프로젝트- 버그수정 디벨롭 (navigate(-1) 등) (0) | 2024.02.07 |