깃허브 특강 및 강의정리

김재현·2023년 10월 24일
1

TIL

목록 보기
14/88
post-thumbnail

오늘은 팀과제 발제, 팀회의(각자의 개인과제 코드 리뷰, 앞으로의 일정), 개인 공부(팀과제를 위한 초석을..!), 깃허브 특강 등이 있었다.

아주 알찬 하루였다고 할 수 있다.

공부하면서 정리한것을 올린다.

Git

매개변수

자바에서 "매개변수"는 메서드(함수)를 호출할 때 메서드에 전달되는 값 또는 데이터를 의미합니다. 메서드는 이러한 매개변수를 사용하여 입력 값을 받고, 해당 값을 처리하거나 연산을 수행한 다음 결과를 반환하거나 특정 작업을 수행할 수 있습니다. 매개변수는 메서드 정의에서 선언되며, 메서드가 호출될 때 매개변수에 전달된 값이 메서드 내에서 사용됩니다.

public int add(int a, int b) {
    // 메서드 내에서 a와 b를 사용하여 두 정수를 더함
    return a + b;
}

위의 코드에서 add 메서드는 int a와 int b라는 두 개의 매개변수를 가지고 있습니다. 이 메서드는 호출될 때 a와 b에 전달된 값들을 사용하여 두 정수를 더하고 결과를 반환합니다.

메서드는 실행할 때 return문을 만나면 그대로 종료하게 되는데 void 타입일 때 return;이렇게 return문을 사용하여 원하는 지점에서 메서드를 종료할 수도 있습니다.!

오버로딩

📌 오버로딩 은 함수가 하나의 기능만을 구현하는것이 아니라 하나의 메서드 이름으로 여러 기능을 구현하도록 하는 Java의 기능입니다.
즉, 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있더라도, 매개변수의 개수 또는 타입, 순서가 다르면 동일한 이름을 사용해서 메서드를 정의할 수 있습니다.
-->장점
1. 메서드 이름 하나로 상황에 따른 동작을 개별로 정의할 수 있습니다.
2. 메서드의 이름을 절약할 수 있습니다.

• 메서드의 이름이 같고, 매개변수의 개수, 타입, 순서가 달라야 합니다.
• '응답 값만' 다른 것은 오버로딩을 할 수 없습니다.
• 접근 제어자만 다른 것도 오버로딩을 할 수 없습니다.
• 결론, 오버로딩은 매개변수의 차이로만 구현할 수 있습니다.

접근제어자

📌 멤버 또는 클래스에 사용, 외부에서 접근하지 못하도록 제한합니다.
• 클래스, 멤버변수, 메서드, 생성자에 사용되고, 지정되어 있지 않다면 default 입니다.
○ public : 접근 제한이 전혀 없습니다.
○ protected : 같은 패키지 내에서, 다른 패키지의 자손클래스에서 접근이 가능합니다
○ default : 같은 패키지 내에서만 접근이 가능합니다.
○ private : 같은 클래스 내에서만 접근이 가능합니다.

Getter
외부에서 객체의 private 한 필드를 읽을 필요가 있을 때 Getter 메서드를 사용합니다.
• 메서드 이름의 규칙은 : get + 필드이름(첫 글자 대문자) 입니다.
• 사용하는 방법은 인스턴스 메서드 호출과 동일합니다.

public String getModel() {
    return model;
}

Setter
외부에서 객체의 private 한 필드를 저장/수정할 필요가 있을 때 Setter 메서드를 사용합니다.
• 메서드 이름의 규칙은 : set + 필드이름(첫 글자 대문자) 입니다.
• 사용하는 방법은 인스턴스 메서드 호출과 동일합니다.

public void setModel(String model) {
    this.model = model;
}

• 사용가능한 제어자
○ 클래스 : public, default, final, abstract
○ 메서드 : public, protected, default, private, final, abstract, static
○ 멤버변수 : public, protected, default, private, final, static
○ 지역변수 : final

클래스

📌 클래스는 Java의 클래스 로더에 의해 메서드 영역에 저장되고 사용됩니다.
• 이때 클래스 멤버란 메서드 영역의 클래스와 같은 위치에 고정적으로 위치하고 있는 멤버를 의미합니다.
• 따라서 클래스 멤버는 객체의 생성 필요없이 바로 사용이 가능합니다.

static String company = "GENESIS"; // 자동차 회사 : GENESIS
String getCompany() {
    return "(주)" + company;
}
Car.company = "Audi";
String companyName = Car.setCompany("Benz");

참조형 변수를 사용하여 클래스 멤버에 접근은 가능하지만 추천하지 않습니다.

Object

말그대로 “객체”를 의미하는 단어이며 보통, Object 클래스를 의미합니다.
• Object 클래스는 Java 내 모든 클래스들의 최상위 부모 클래스 입니다.
• 따라서, 모든 클래스는 Object의 메서드를 사용할 수 있습니다.
• 또한 부모 클래스가 없는 자식 클래스는 컴파일러에 의해 자동으로 Object 클래스를 상속받게 됩니다.

몇가지 예시
• Object clone() : 해당 객체의 복제본을 생성하여 반환함.
• boolean equals(Object object) : 해당 객체와 전달받은 객체가 같은지 여부를 반환함.
• Class getClass() : 해당 객체의 클래스 타입을 반환함.
• int hashCode() : 자바에서 객체를 식별하는 정수값인 해시 코드를 반환함.
• String toString() : 해당 객체의 정보를 문자열 로 반환함. & Object 클래스에서는 클래스이름 @해쉬코드값 리턴함.

super는 부모 클래스의 멤버를 참조할 수 있는 키워드입니다.

• 객체 내부 생성자 및 메서드에서 부모 클래스의 멤버에 접근하기 위해 사용될 수 있습니다.
• 자식 클래스 내부에서 선언한 멤버와 부모 클래스에서 상속받은 멤버와 이름이 같을 경우 이를 구분하기 위해 사용됩니다.

// 부모 클래스 Car
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격

// 자식 클래스 SportsCar
String model = "Ferrari"; // 자동차 모델
String color = "Red"; // 자동차 색상
double price = 300000000; // 자동차 가격

//자식 클래스의 메서드
public void setCarInfo(String model, String color, double price) {
    super.model = model; // model은 부모 필드에 set
    super.color = color; // color는 부모 필드에 set
    this.price = price; // price는 자식 필드에 set
}

오버라이딩

부모 클래스로부터 상속받은 메서드의 내용을 재정의 하는 것을 오버라이딩이라고 합니다.

  1. 선언부가 부모 클래스의 메서드와 일치해야 합니다.
  2. 접근 제어자를 부모 클래스의 메서드 보다 좁은 범위로 변경할 수 없습니다.
  3. 예외는 부모 클래스의 메서드 보다 많이 선언할 수 없습니다.
public class SportsCar extends Car{
    String engine;
    public void booster() {
        System.out.println("엔진 " + engine + " 부앙~\n");
    }

    public SportsCar(String engine) {
        this.engine = engine;
    }

    @Override
    public double brakePedal() {
        speed = 100;
        System.out.println("스포츠카에 브레이크란 없다");
        return speed;
    }

    @Override
    public void horn() {
        booster();
    }
}

super(…)

부모 클래스의 생성자를 호출할 수 있는 키워드입니다.
• 객체 내부 생성자 및 메서드에서 해당 객체의 부모 클래스의 생성자를 호출하기 위해 사용될 수 있습니다.
• 자식 클래스의 객체가 생성될 때 부모 클래스들이 모두 합쳐져서 하나의 인스턴스가 생성됩니다.
• 이 때 부모 클래스의 멤버들의 초기화 작업이 먼저 수행이 되어야합니다.
○ 따라서 자식 클래스의 생성자에서는 부모 클래스의 생성자가 호출됩니다.
○ 또한 부모 클래스의 생성자는 가장 첫 줄에서 호출이 되어야합니다.

// 부모 클래스 Car 생성자
public Car(String model, String color, double price) {
this.model = model;
this.color = color;
this.price = price;
}

// 자식 클래스 SportsCar 생성자
public SportsCar(String model, String color, double price, String engine) {
// this.engine = engine; // 오류 발생
super(model, color, price);
this.engine = engine;
}

참조변수의 타입변환

자동 타입변환

부모타입 변수 = 자식타입객체;는 자동으로 부모타입으로 변환이 일어납니다.
-> 다만 주의할 점은 부모타입 변수로 자식객체의 멤버에 접근할 때는 부모 클래스에 선언된 즉, 상속받은 멤버만 접근할 수 있습니다.

강제 타입변환

자식타입 변수 = (자식타입) 부모타입객체;
• 부모타입객체는 자식타입 변수로 자동으로 타입변환되지 않습니다.
• 이럴때는 (자식타입) 즉, 타입변환 연산자를 사용하여 강제로 자식타입으로 변환할 수 있습니다.

// 자식타입객체가 자동 타입변환된 부모타입의 변수
Mammal mammal = new Whale();
mammal.feeding();

// 자식객체 고래의 수영 기능을 사용하고 싶다면
// 다시 자식타입으로 강제 타입변환을 하면된다.
Whale whale = (Whale) mammal;
whale.swimming();

• 다만 무조건 강제 타입변환을 할 수 있는 것은 아닙니다.
○ 자식타입객체가 부모타입으로 자동 타입변환된 후 다시 자식타입으로 변환될 때 만 강제 타입변환이 가능합니다.
○ 부모타입 변수로는 자식타입객체의 고유한 멤버를 사용할 수 없기 때문에 사용이 필요한 경우가 생겼을 때 강제 타입변환을 사용합니다.

Mammal newMammal = new Mammal();
Whale newWhale = (Whale) newMammal; // ClassCastException 발생

☆다형성

다형성이란 ‘여러 가지 형태를 가질 수 있는 능력’을 의미합니다.

Tire tire = new HankookTire("HANKOOK");
Tire tire = new KiaTire("KIA");

• 부모타이어 변수 = 자식타이어객체;를 선언하여 자동 타입변환된 변수를 사용하여 각각의 자식타이어 객체에 재정의 된 메서드를 통해 다양한 승차감을 가진 자동차를 생성할 수 있습니다.

public Car(Tire tire) {
    this.tire = tire;
}

	...

Car car1 = new Car(new KiaTire("KIA"));
Car car2 = new Car(new HankookTire("HANKOOK"));

• 매개변수에도 다형성이 적용될 수 있습니다.
• Car 생성자에서 매개변수의 타입이 부모 타이어 이기 때문에 자식 타이어 객체들을 매개값으로 전달할 수 있습니다.

Tire getHankookTire() {
    return new HankookTire("HANKOOK");
}

Tire getKiaTire() {
    return new KiaTire("KIA");
}

	...

Tire hankookTire = car1.getHankookTire();
KiaTire kiaTire = (KiaTire) car2.getKiaTire();

• 반환타입에도 다형성이 적용될 수 있습니다.
• 반환타입이 부모 타이어 이기 때문에 자식 타이어 객체들을 반환값으로 지정할 수 있습니다.
• 또한 자동 타입변환이된 반환값인 자식 타이어 객체를 강제 타입변환할 수도 있습니다.

instanceof

📌 다형성 기능으로 인해 해당 클래스 객체의 원래 클래스명을 체크하는것이 필요한데 이때 사용할 수 있는 명령어가 instance of 입니다.
• 이 명령어를 통해서 해당 객체가 내가 의도하는 클래스의 객체인지 확인할 수 있습니다.
• {대상 객체} instance of {클래스 이름} 와 같은 형태로 사용하면 응답값은 boolean 입니다.

추상 클래스, 메서드

📌 클래스가 설계도라면 추상 클래스는 미완성된 설계도입니다.
• abstract 키워드를 사용하여 추상 클래스를 선언할 수 있습니다.
public abstract class 추상클래스명 {}
• 추상 클래스는 추상 메서드를 포함할 수 있습니다.
○ 추상 메서드가 없어도 추상 클래스로 선언할 수 있습니다.
• 추상 클래스는 자식 클래스에 상속되어 자식 클래스에 의해서만 완성될 수 있습니다.
• 추상 클래스는 여러개의 자식 클래스들에서 공통적인 필드나 메서드를 추출해서 만들 수 있습니다.

📌 추상 메서드는 아직 구현되지 않은 미완성된 메서드입니다.
• abstract 키워드를 사용하여 추상 메서드를 선언할 수 있습니다.

		public abstract class 추상클래스명 {
		abstract 리턴타입 메서드이름(매개변수, ...);
}

추상 메서드는 일반적인 메서드와는 다르게 블록{ }이 없습니다.
즉, 정의만 할 뿐, 실행 내용은 가지고 있지 않습니다.

📌 추상 메서드는 extends 키워드를 사용하여 클래스에서 상속됩니다.

		public class 클래스명 extends 추상클래스명 {
		@Override
    public 리턴타입 메서드이름(매개변수, ...) {
		       // 실행문
    }
}

상속받은 클래스에서 추상 클래스의 추상 메서드는 반드시 오버라이딩 되어야 합니다.

인터페이스

📌 인터페이스의 역할에 대해 학습해보겠습니다.
• 인터페이스는 두 객체를 연결해주는 다리 역할을 해줍니다.
• 상속 관계가 없는 다른 클래스들이 서로 동일한 행위 즉, 메서드를 구현해야할 때 인터페이스는 구현 클래스들의 동일한 사용 방법과 행위를 보장해 줄 수 있습니다.
○ 인터페이스는 스팩이 정의된 메서드들의 집합입니다.
○ 인터페이스의 구현 클래스들은 반드시 정의된 메서드들을 구현해야합니다.
○ 따라서 구현 클래스들의 동일한 사용 방법과 행위를 보장해 줄 수 있습니다.
○ 이러한 특징은 인터페이스에 다형성을 적용할 수 있게 만들어 줍니다.
• 모든 멤버변수는 public static final 이어야합니다.
○ 생략 가능합니다.
• 모든 메서드는 public abstract 이어야합니다.
○ 생략 가능합니다. (static 메서드와 default 메서드 예외)
• 생략되는 제어자는 컴파일러가 자동으로 추가 해줍니다.

	public interface 인터페이스명 { 
	    public static final char A = 'A';
	    static char B = 'B';
	    final char C = 'C';
	    char D = 'D';
	
	    void turnOn(); // public abstract void turnOn();
	}

📌 인터페이스는 추상 클래스와 마찬가지로 직접 인스턴스를 생성할 수 없기 때문에 클래스에 구현되어 생성됩니다.
• implements 키워드를 사용하여 인터페이스를 구현할 수 있습니다.

	public class 클래스명 implements 인터페이스명 { 
				// 추상 메서드 오버라이딩
				@Override
		    public 리턴타입 메서드이름(매개변수, ...) {
				       // 실행문
		    }
	}

• 인터페이스의 추상 메서드는 구현될 때 반드시 오버라이딩 되어야 합니다.
• 만약 인터페이스의 추상 메서드를 일부만 구현해야 한다면 해당 클래스를 추상 클래스로 변경해주면 됩니다.

📌 인터페이스간의 상속이 가능합니다.
• 인터페이스간의 상속은 implements 가 아니라 extends 키워드를 사용합니다.
• 인터페이스는 클래스와는 다르게 다중 상속이 가능합니다.

public class Main implements C {

    @Override
    public void a() {
        System.out.println("A");
    }

    @Override
    public void b() {
				System.out.println("B");
    }
}

interface A {
    void a();
}
interface B {
    void b();
}
interface C extends A, B { }

• 또한 인터페이스의 구현은 상속과 함께 사용될 수 있습니다.

디폴트 메서드와 static 메서드

📌 디폴트 메서드는 추상 메서드의 기본적인 구현을 제공하는 메서드입니다.
• 메서드 앞에 default 키워드를 붙이며 블럭{ }이 존재해야합니다.
• default 메서드 역시 접근 제어자가 public 이며 생략이 가능합니다.
• 추상 메서드가 아니기 때문에 인터페이스의 구현체들에서 필수로 재정의 할 필요는 없습니다.

public class Main implements A {

    @Override
    public void a() {
        System.out.println("A");
    }


    public static void main(String[] args) {
        Main main = new Main();
        main.a();

        // 디폴트 메서드 재정의 없이 바로 사용가능합니다.
        main.aa();
    }
}

interface A {
    void a();
    default void aa() {
        System.out.println("AA");
    }
}

📌 인터페이스에서 static 메서드 선언이 가능합니다.
• static의 특성 그대로 인터페이스의 static 메서드 또한 객체 없이 호출이 가능합니다.
• 선언하는 방법과 호출하는 방법은 클래스의 static 메서드와 동일합니다.
○ 접근 제어자를 생략하면 컴파일러가 public을 추가해 줍니다.

public class Main implements A {

    @Override
    public void a() {
        System.out.println("A");
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.a();
        main.aa();
        System.out.println();

        // static 메서드 aaa() 호출
        A.aaa();
    }
}

interface A {
    void a();
    default void aa() {
        System.out.println("AA");
    }
    static void aaa() {
        System.out.println("static method");
    }
}

☆☆다형성☆☆

자동 타입 변환
인터페이스 변수 = 구현객체;는 자동으로 타입 변환이 일어납니다.

public class Main {
    public static void main(String[] args) {
        
        // A 인터페이스에 구현체 B 대입
        A a1 = new B();
        
        // A 인터페이스에 구편체 B를 상속받은 C 대입
        A a2 = new C();
        
    }
}


interface A { }
class B implements A {}
class C extends B {}

강제 타입 변환
구현객체타입 변수 = (구현객체타입) 인터페이스변수;

public class Main {
    public static void main(String[] args) {

        // A 인터페이스에 구현체 B 대입
        A a1 = new B();
        a1.a();
        // a1.b(); // 불가능

        System.out.println("\nB 강제 타입변환");
        B b = (B) a1;
        b.a();
        b.b(); // 강제 타입변환으로 사용 가능
        System.out.println();

        // A 인터페이스에 구편체 B를 상속받은 C 대입
        A a2 = new C();
        a2.a();
        //a2.b(); // 불가능
        //a2.c(); // 불가능

        System.out.println("\nC 강제 타입변환");
        C c = (C) a2;
        c.a();
        c.b(); // 강제 타입변환으로 사용 가능
        c.c(); // 강제 타입변환으로 사용 가능


    }
}

interface A {
    void a();
}
class B implements A {
    @Override
    public void a() {
        System.out.println("B.a()");
    }

    public void b() {
        System.out.println("B.b()");
    }
}
class C extends B {
    public void c() {
        System.out.println("C.c()");
    }
}

인터페이스의 다형성

// LG TV 구현체를 조작
MultiRemoteController mrc = new LgTv("LG");
mrc.turnOnOff();
mrc.volumeUp();

// 조작 대상을 Samsung TV로 교체
mrc = new SamsungTv("Samsung");
mrc.turnOnOff();
mrc.channelUp();

• 멀티리모컨인터페이스 변수 = TV구현객체; 를 선언하여 자동 타입변환된 인터페이스 변수를 사용하여 TV구현객체의 기능을 조작할 수 있습니다.
• TV구현객체를 교체해도 멀티리모컨인터페이스 변수는 전혀 수정작업 없이 그대로 기능을 호출할 수 있습니다.
• 다형성은 ‘여러 가지 형태를 가질 수 있는 능력’ 이라고 배웠습니다.
• 사용 방법은 동일하지만 다양한 특징과 결과를 가질 수 있는 것이 바로 다형성입니다.
○ 즉, 멀티리모컨으로 티비를 사용하는 방법은 동일하지만 어떤 TV구현객체가 대입되었느냐에 따라 실행 결과가 다르게 나옴을 통해 다형성이 적용되었음을 확인할 수 있었습니다.

// 매개변수와 반환타입 다형성 확인 메서드

default MultiRemoteController getTV(Tv tv) {
    if(tv instanceof SamsungTv) {
        return (SamsungTv) tv;
    } else if(tv instanceof LgTv){
        return (LgTv) tv;
    } else {
        throw new NullPointerException("일치하는 Tv 없음");
    }
}

• 또한 인터페이스도 마찬가지로 매개변수와 반환타입에서 다형성이 적용될 수 있습니다.
• 위 예제는 반환타입에는 인터페이스, 매개변수에는 추상클래스로 다형성이 적용되어있습니다.
○ 인터페이스의 default 메서드입니다.

profile
I live in Seoul, Korea, Handsome

0개의 댓글