CodeGym/Java Blog/무작위의/Java의 OOP 개념
John Squirrels
레벨 41
San Francisco

Java의 OOP 개념

무작위의 그룹에 게시되었습니다
회원
Java의 가장 큰 장점 중 하나는 객체 지향 프로그래밍(OOP)입니다. 이것이 이 언어가 대중화되고 모든 규모의 프로젝트에 적합한 이유입니다. 객체 지향 프로그래밍이란 무엇입니까? 마술은 아니지만 실제로 들어가면 마술처럼 보일 수 있습니다. OOP는 소프트웨어를 구축하는 방법에 관한 것입니다. 소프트웨어를 효과적으로 개발하고 사용하기 위해 Java 개체 간의 특정 상호 작용 및 관계를 생성할 수 있는 개념 또는 Java의 oop 개념입니다. Java의 OOP 개념 - 1고전적인 OOP에는 3 + 1 주요 개념이 포함됩니다. 고전부터 시작합시다.

그 물체

Java 객체와 실제 객체에는 상태와 동작이라는 두 가지 특성이 있습니다.

예를 들어 Human 개체에는 상태(이름, 성별, 수면 여부...) 및 동작(Java 공부, 걷기, 대화...)이 있습니다. 모든 Java 개체는 상태를 필드에 저장하고 메서드를 통해 동작을 노출합니다.

캡슐화

데이터 캡슐화는 외부 세계로부터 내부 데이터를 숨기고 공개적으로 노출된 방법을 통해서만 액세스합니다. 그게 무슨 뜻이야? 어떤 데이터? 누구에게 숨기고 있습니까? 숨기는 것은 클래스의 데이터 멤버(필드)에 대한 직접 액세스를 제한하는 것을 의미합니다.

자바에서 작동하는 방식:

  1. 필드가 비공개로 설정됨
  2. 클래스의 각 필드에는 getter와 setter라는 두 가지 특수 메서드가 있습니다. Getter 메서드는 필드 값을 반환합니다. Setter 메서드를 사용하면 간접적이지만 허용되는 방식으로 필드 값을 변경할 수 있습니다.

Java 코드의 캡슐화 예:

public class Student {
private int age;
private String name;

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

public class Test{
public static void main(String[] args) {
Student firstStudent = new Student();
firstStudent.setName("John");
// The name field is private, so you can no longer do this:  firstStudent.name = "John";
}
}

캡슐화를 사용해야 하는 이유는 무엇입니까?

주된 이유는 코드를 쉽게 변경할 수 있도록 하기 위함입니다. 하키 학교 지원서가 있고 학교에 등록한 학생의 이름과 나이를 저장하는 두 개의 필드가 있는 HockeyStudent 클래스가 있다고 가정해 보십시오. 이 같은:
public class HockeyStudent {
public String name;
public  int ageOfEnrollment;
}
ageOfEnrollment 필드는 공용이며 getter 또는 setter가 없습니다. 이 클래스는 다른 많은 클래스에서 사용되며 일부 개발자가 단일 int 필드가 충분하지 않다고 결정할 때까지 모든 것이 정상이었습니다 . 코호트의 일부 하키 선수는 동료보다 거의 한 살이 많기 때문에 태어난 달에 따라 두 그룹으로 나누는 것이 더 편리할 것입니다. 따라서 ageOfEnrollment 필드는 int 배열(int[][]) 로 변경되어야 합니다 . 첫 번째 숫자는 만년이고 두 번째 숫자는 월입니다. 이제 Student 클래스 를 사용하는 모든 코드를 리팩터링해야 합니다 ! 그러나 귀하의 ageOfEnrollment필드는 비공개이고 게터와 세터가 있으면 모든 것이 더 쉽습니다. 학생의 나이 설정에 대한 요구 사항이 변경되면 setAgeOfEnrollment() setter 메서드 의 논리를 업데이트하기만 하면 수업에서 아무 문제 없이 계속해서 Student를 사용할 수 있습니다 ! 이 예제는 다소 인위적이지만 캡슐화를 사용하는 것이 좋은 이유를 설명하기를 바랍니다.

계승

이 원칙은 실제 경험이 없어도 이해하기 쉽습니다. Don't repeat yourself(DRY)는 상속 개념의 모토가 될 수 있습니다. 상속을 사용하면 부모 클래스의 필드와 메서드를 재정의하지 않고 상속하는 자식 클래스를 만들 수 있습니다. 물론 자식 클래스에서 부모 클래스의 필드와 메서드를 재정의할 수 있지만 필수는 아닙니다. 또한 자식 클래스에 새로운 상태와 동작을 추가할 수 있습니다. 상위 클래스는 수퍼클래스 또는 기본 클래스라고도 하며 하위 클래스는 하위 클래스라고 합니다. Java의 extends 키워드는 코드에서 상속 원칙을 구현하는 데 사용됩니다.

자바에서 작동하는 방식:

  1. 부모 클래스를 만듭니다.
  2. extends 키워드를 사용하여 자식 클래스를 만듭니다 .
  3. Child 클래스의 생성자에서 super(parentField1, parentField2, ...) 메서드를 사용하여 부모의 필드를 설정합니다.

생성자는 새로 생성된 개체를 초기화하는 데 사용되는 특수 메서드입니다. 생성자는 클래스 이름과 동일한 이름을 갖습니다. 생성자에는 기본(인수 없는 생성자) 및 매개 변수가 있는 생성자의 두 가지 유형이 있습니다. 클래스에는 적어도 하나의 생성자가 있어야 하며(다른 생성자가 정의되지 않은 경우 기본 생성자가 있음) 많은 생성자를 가질 수 있습니다.

새 개체를 만들 때마다 해당 생성자를 호출합니다. 위의 예에서 다음 행에서 이 작업을 수행합니다.

Student firstStudent = new Student();

new 키워드를 사용하여 Student 클래스의 기본 생성자인 tudent() 를 호출합니다 .

몇 가지 규칙:

  1. 하나의 클래스에는 하나의 부모만 있을 수 있습니다.
  2. 하나의 부모 클래스는 많은 자식 클래스를 가질 수 있습니다.
  3. 하위 클래스는 자체 하위 클래스를 가질 수 있습니다.

Java 코드의 상속 예

전화 클래스를 만들어 봅시다 .
public class Phone {
    int price;
    double weight;

// Constructor
public Phone(int price, double weight) {
        this.price = price;
        this.weight = weight;
    }

    void orderPhone(){
        System.out.println("Ordering phone...");
    }
}
물론 다른 유형의 전화가 있으므로 두 개의 자식 클래스를 만들어 보겠습니다. 하나는 Android 휴대폰용이고 다른 하나는 iPhone용입니다. 그런 다음 부모에 없는 일부 필드와 메서드를 추가합니다. 그리고 부모 클래스가 가지고 있는 필드를 초기화하기 위해 생성자를 호출하기 위해 super()를 사용할 것입니다 .

Java에서 상속의 예

public class Android extends Phone {

// Some new fields
String androidVersion;
int screenSize;

    String secretDeviceCode;

// Constructor
    public Android(int price, double weight, String androidVersion, int screenSize, String secretDeviceCode) {
        super(price, weight); // Android inherits Phone’s fields

        //this - reference to the current object
        //super - reference to the parent object

        this.androidVersion = androidVersion;
        this.screenSize = screenSize;
        this.secretDeviceCode = secretDeviceCode;
    }

	// New Android-specific method, does not exist in the Phone class
    void installNewAndroidVersion() {
        System.out.println("installNewAndroidVersion invoked...");

    }

}

public class IPhone extends Phone {

    boolean fingerPrint;

    public IPhone(int price, double weight, boolean fingerPrint) {
        super(price, weight);
        System.out.println("IPhone constructor was invoked...");
        this.fingerPrint = fingerPrint;
    }

    void deleteIPhoneFromDb() {
        System.out.println("deleteIPhoneFromDb invoked...");
    }

@Override // This is about polymorphism, see below
void orderPhone(){
        System.out.println("Ordering my new iPhone and deleting the old one...");
    }
}
반복하자면, Java에서는 상속을 통해 부모 클래스의 필드와 메서드를 상속하는 자식 클래스로 클래스를 확장할 수 있습니다. 코드 재사용성을 달성하는 훌륭한 방법입니다.

다형성

다형성(Polymorphism)은 다른 형태를 취하거나 오히려 다른 방식으로 행동하는 객체의 모핑 능력입니다. Java에서 다형성은 일반적으로 상위 클래스 참조가 하위 클래스 객체를 참조하는 데 사용될 때 발생합니다.

이것이 무엇을 의미하고 Java에서 어떻게 작동하는지:

Java의 다형성이란 무엇입니까? 일반적으로 이는 다른 용도로 동일한 메서드 이름을 사용할 수 있음을 의미합니다. Java에는 메서드 재정의(동적 다형성)와 메서드 오버로딩(정적 다형성)의 두 가지 유형의 다형성이 있습니다.

메서드 재정의

자식 클래스에서 부모 클래스의 메서드를 재정의하여 다른 방식으로 작동하도록 할 수 있습니다. play() 메서드를 사용하여 Musician 부모 클래스를 만들어 봅시다 .

Java 코드의 다형성 예

public class Musician {
    String name;
    int age;

    // Default constructor
    public Musician() {
    }

    // Parameterized constructor
    public Musician(String name, int age) {
        this.name = name;
        this.age = age;
    }

    void play() {
        System.out.println("I am playing my instrument...");
    }
}
다른 음악가들은 다른 악기를 사용합니다. PianistViolinist 라는 두 개의 자식 클래스를 만들어 봅시다 . 다형성 덕분에 각각 고유한 버전의 play() 메서드를 실행합니다. 재정의할 때 @Override 주석을 사용할 수 있지만 필수는 아닙니다.
public class Pianist extends Musician {

    String favoritePianoType;

    public Pianist(String name, int age, String favoritePianoType) {
        super(name, age);
        this.favoritePianoType = favoritePianoType;
    }


    @Override
void play(){
        System.out.println("I am playing the piano...");
    }
}
바이올린 연주자는 솔리스트가 될 수도 있고 오케스트라 단원이 될 수도 있습니다. play() 메서드 를 재정의할 때 이를 고려하십시오 .
public class Violinist extends Musician {
    boolean isSoloist;

public Violinist(String name, int age, boolean isSoloist) {
            super(name, age);
            this.isSoloist = isSoloist;
        }


    @Override
void play(){
if (isSoloist)
        System.out.println("I am playing the violin solo...");
else
System.out.println("I am playing the violin in an orchestra...");

    }
}
이전에 생성된 각 클래스의 인스턴스인 세 개의 객체를 생성할 데모 클래스를 생성해 보겠습니다 . 우리는 우리가 얻는 결과를 볼 것입니다.
public class Demo {
  public static void main(String[] args) {
  Musician musician = new Musician();
  Violinist violinist = new Violinist("John", 32, true);
  Pianist pianist = new Pianist("Glen", 30, "Acoustic");

  System.out.println("Musician said:");
  musician.play();
  System.out.println("Violinist said:");
  violinist.play();
  System.out.println("Pianist said:");
  pianist.play();
    }
}
우리가 얻는 것은 다음과 같습니다.
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo…
Pianist said:
I am playing the piano...
모든 바이올리니스트와 피아니스트는 음악가이지만 모든 음악가가 비올리스트나 피아니스트는 아닙니다. 즉, 새로 만들 필요가 없는 경우 뮤지션의 연주 방법을 사용할 수 있습니다. 또는 super 키워드 를 사용하여 자식에서 부모의 메서드를 호출할 수 있습니다 . Pianist의 코드에서 해봅시다.
public class Pianist extends Musician {

    String favoritePianoType;

    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
}
이제 Demo 클래스 에서 main() 메서드를 호출해 보겠습니다 . 결과는 다음과 같습니다.
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...

메소드 오버로딩

메소드 오버로딩은 같은 클래스에서 같은 이름을 가진 다양한 메소드를 사용하는 것을 의미합니다. 매개변수의 수, 순서 또는 유형이 달라야 합니다. 피아니스트가 어쿠스틱 피아노와 전자 피아노를 연주할 수 있다고 가정합니다. 전기를 연주하려면 음악가에게 전기가 필요합니다. 두 가지 다른 play() 메서드를 만들어 봅시다 . 첫 번째는 매개변수가 없는 어쿠스틱 피아노용이고 두 번째는 전기 사용 가능 여부를 나타내는 매개변수가 있는 것입니다.
public class Pianist extends Musician {

    String name;
    int age;
    String favoritePianoType;

    @Override
    void play(){
        super.play();
        System.out.println("I am playing the piano...");
    }
    void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            System.out.println("I am playing the piano...");
        }
        else System.out.println("I can't play this without electricity.");
    }
}
그건 그렇고, 다음과 같은 방식으로 두 번째 play(boolean) 메서드 내에서 첫 번째 play() 메서드를 사용할 수 있습니다.
void play(boolean isElectricity){
        if (isElectricity) {
            System.out.println("The electricity is on.");
            play();
        }
        else System.out.println("I can't play this without electricity.");
    }
오버 로드를 보여주기 위해 데모 클래스 에 몇 줄을 추가해 보겠습니다 .
public class Demo {
    public static void main(String[] args) {

        Musician musician = new Musician();
        Violinist violinist = new Violinist("John", 23, true);
        Pianist pianist = new Pianist("Glen", 30, "Acoustic");

        System.out.println("Musician said:");
        musician.play();
        System.out.println("Violinist said:");
        violinist.play();
        System.out.println("Pianist said:");
        pianist.play();
        System.out.println("The pianist will now try the electric piano:");
        pianist.play(true);
        System.out.println("The electricity has been shut off. Now when trying the electric piano, the pianist says:");
        pianist.play(false);
    }
}
결과는 다음과 같습니다.
Musician said:
I am playing my instrument...
Violinist said:
I am playing the violin solo...
Pianist said:
I am playing my instrument...
I am playing the piano...
The pianist will now try the electric piano:
The electricity is on.
I am playing my instrument...
I am playing the piano...
The electricity has been shut off. Now when trying the electric piano, the pianist says:
I can't play this without electricity.
Java는 매개변수와 객체 유형에 따라 어떤 메서드를 사용해야 하는지 알고 있습니다. 다형성입니다.

추출

클래스를 정의할 때 우리는 무언가의 모델을 구축하려고 합니다. 예를 들어 다양한 경주용 자동차로 MyRacer라는 비디오 게임을 작성한다고 가정합니다. 플레이어는 그 중 하나를 선택한 다음 나중에 업데이트하거나 다른 것을 구입할 수 있습니다. 그래서... 자동차란? 자동차는 꽤 복잡한 것이지만 레이싱 비디오 게임(드라이빙 시뮬레이터와 반대)을 만들려고 한다면 자동차에 포함된 수천 개의 기어와 개스킷을 모두 설명할 필요가 없습니다. 모델, 최고 속도, 기동성 특성, 가격, 색상이 필요합니다… 그리고 아마도 그것으로 충분할 것입니다. 이것이 우리 게임의 자동차 모델입니다. 나중에 MyRacer 2에서 도로 핸들링에 영향을 미치는 타이어를 추가하기로 결정했다고 가정합니다. 여기에서는 모델이 다릅니다. 자세한 내용을 추가했기 때문입니다. 허락하다' s는 객체의 중요한(또는 필요한) 특성만 식별하고 관련 없는 세부 사항은 무시하는 프로세스로 데이터 추상화를 정의합니다. 다양한 수준의 추상화가 있습니다. 예를 들어, 당신이 버스에 탄 승객이라면 버스가 어떻게 생겼는지, 어디로 가는지 알아야 하지만 운전 방법은 알 필요가 없습니다. 버스 운전사라면 새 버스를 만드는 방법을 알 필요가 없습니다. 운전 방법만 알면 됩니다. 그러나 버스 제조업체의 경우 버스 설계의 세부 사항이 매우 중요하기 때문에 낮은 수준의 추상화로 이동해야 합니다. 나는 당신이 내가 의미하는 바를 이해하기를 바랍니다. 버스가 어떻게 생겼는지, 어디로 가는지 알아야 하지만 버스를 운전하는 방법을 알 필요는 없습니다. 버스 운전사라면 새 버스를 만드는 방법을 알 필요가 없습니다. 운전 방법만 알면 됩니다. 그러나 버스 제조업체의 경우 버스 설계의 세부 사항이 매우 중요하기 때문에 낮은 수준의 추상화로 이동해야 합니다. 나는 당신이 내가 의미하는 바를 이해하기를 바랍니다. 버스가 어떻게 생겼는지, 어디로 가는지 알아야 하지만 버스를 운전하는 방법을 알 필요는 없습니다. 버스 운전사라면 새 버스를 만드는 방법을 알 필요가 없습니다. 운전 방법만 알면 됩니다. 그러나 버스 제조업체의 경우 버스 설계의 세부 사항이 매우 중요하기 때문에 낮은 수준의 추상화로 이동해야 합니다. 나는 당신이 내가 의미하는 바를 이해하기를 바랍니다.

자바에서 작동하는 방식:

Java 또는 OOP에서 가장 낮은 수준(가장 구체적)에서 가장 높은 수준(가장 추상적인 것)까지 네 가지 수준의 추상화를 구축해 봅시다.
  1. 가장 낮은 수준의 추상화는 특정 개체입니다. 특정 클래스에 속하는 일련의 특성을 가진 엔터티입니다. 특정 필드 값이 있습니다.

  2. 개체를 만들기 위한 템플릿은 클래스입니다. 유사한 속성과 내부 구조를 가진 개체 집합에 대한 설명입니다.

  3. 추상 클래스는 클래스 집합의 특성에 대한 추상적인 설명입니다(다른 클래스에 의한 상속을 위한 템플릿 역할을 함). 추상화 수준이 높기 때문에 추상 클래스에서 직접 객체를 생성하는 것은 불가능합니다. 추상 클래스의 자식 클래스만 개체를 ​​만드는 데 사용할 수 있습니다. 추상 클래스는 구현이 있는 메서드를 포함할 수 있지만 필수 사항은 아닙니다.

  4. 인터페이스는 추상 공용 메서드와 정적 상수 필드(최종 정적)만 포함하는 Java 프로그래밍 언어 구성의 구성입니다. 즉, 객체를 생성하는 데 추상 클래스나 인터페이스를 사용할 수 없습니다.

BTW, Java 8 이상에서 인터페이스는 추상 메서드 및 상수뿐만 아니라 기본 및 정적 메서드도 가질 수 있습니다. Java에서 인터페이스는 동작을 정의하는 반면 추상 클래스는 계층 구조를 만드는 데 사용됩니다. 하나의 인터페이스를 여러 클래스로 구현할 수 있습니다.

Java 코드의 인터페이스 예

interface Human {
	public void struggle();
	public void protect();
}

interface Vulcan {
	int angleOfPointyEars;
	public void turnOffEmotions(boolean isOn);
	public void telepathy();
}
둘 이상의 인터페이스를 구현할 수 있습니다.
The Spock class implements Human and Vulcan {
public void struggle() {
System.out.println("I am struggling...");
}
	public void protect() {
System.out.println("You are under my protection!);
}
public void turnOffEmotions(boolean isOn){
If (isOn) {
System.out.println("I am turning off my emotions.");
isOn= !isOn;
}
}
	public void telepathy() {
System.out.println("Connecting to your brain...");
}

}
초급 학생의 경우 Java에서 객체 지향 프로그래밍의 모든 주요 개념을 다룹니다. 4가지 주요 OOP 원칙 외에도 Java에는 연관, 집계 및 구성이 있습니다. 이를 "추가 OOP 원칙"이라고 부를 수 있습니다. 그들은 별도의 기사를 쓸 자격이 있습니다.
코멘트
  • 인기
  • 신규
  • 이전
코멘트를 남기려면 로그인 해야 합니다
이 페이지에는 아직 코멘트가 없습니다