> Java > Java베이스 > Java의 상속에 대한 자세한 설명

Java의 상속에 대한 자세한 설명

풀어 주다: 2019-11-25 16:45:12
앞으로
2307명이 탐색했습니다.

Java의 상속에 대한 자세한 설명

Java 상속 및 합성의 기본 개념

상속: can 기존 클래스에서 새 클래스를 생성합니다. 기존 클래스를 상속하면 해당 클래스의 메서드와 필드를 재사용할 수 있습니다. 이를 바탕으로 새로운 메소드와 필드를 추가하여 클래스의 기능을 확장할 수 있습니다.

합성: 새 클래스에서 독창적인 개체를 만드는 것을 합성이라고 합니다. 이렇게 하면 형식을 변경하지 않고도 기존 코드를 재사용할 수 있습니다.

추천 관련 비디오 튜토리얼: java 비디오 튜토리얼

1 상속된 구문

# 🎜 🎜#extends 키워드는 새 클래스가 기존 클래스에서 파생되었음을 나타냅니다. 기존 클래스를 상위 클래스 또는 기본 클래스라고 하고, 새 클래스를 하위 클래스 또는 파생 클래스라고 합니다. 예:

class Student extends Person {

}
로그인 후 복사

The 클래스 Student는 Person을 상속합니다. Person 클래스는 상위 클래스 또는 기본 클래스라고 하며 Student 클래스는 하위 클래스 또는 파생 클래스라고 합니다.

2. 합성 구문

합성은 클래스 내에 기존 클래스를 만드는 비교적 간단합니다.

class Student {
    Dog dog;
}
로그인 후 복사

스타일 업데이트 중

1. 기본 컨셉 #🎜🎜 #상속의 역할은 코드 재사용에 있습니다. 상속이란 부모 클래스의 모든 메서드를 자식 클래스에서도 사용할 수 있다는 의미이므로 부모 클래스에 보낸 메시지를 파생 클래스에도 보낼 수 있습니다. Person 클래스에 eat 메소드가 있으면 Student 클래스에도 이 메소드가 있을 것입니다. 이는 Student 객체도 Person 유형임을 의미합니다.

class Person {
    public void eat() {
        System.out.println("eat");
    }

    static void show(Person p) {
        p.eat();
    }
}
public class Student extends Person{
    public static void main(String[] args) {
        Student s = new Student();
        Person.show(s);     // ①
    }
}
로그인 후 복사

[실행 결과]:

eat


Person에 정의된 show 메소드는 Person 핸들을 수신하는 데 사용되지만, ①에서 수신된 것은 A 참조입니다. 학생 개체에. 이는 Student 개체가 Person 개체이기도 하기 때문입니다. show 메소드에서 수신 핸들(객체 참조)은 Person 객체 및 Person 파생 클래스 객체일 수 있습니다. Student 핸들을 Person 핸들로 변환하는 이러한 동작을 업캐스팅이라고 합니다.

2. 왜 모양을 추적해야 할까요? show 메소드가 단순히 Student 핸들을 얻는다면 더 직관적이고 이해하기 쉬워 보이지만 그렇게 하려면 Person 클래스에서 파생된 각각의 새 클래스가 자체 show 메소드를 구현해야 합니다.

class Value {
    private int count = 1;

    private Value(int count) {
        this.count = count;
    }

    public static final Value
            v1 = new Value(1),
            v2 = new Value(2),
            v3 = new Value(3);
}

class Person {

    public void eat(Value v) {
        System.out.println("Person.eat()");
    }
}

class Teacher extends Person {
    public void eat(Value v) {
        System.out.println("Teacher.eat()");
    }
}

class Student extends Person {
    public void eat(Value v) {
        System.out.println("Student.eat()");
    }
}

public class UpcastingDemo {
    public static void show(Student s) {
        s.eat(Value.v1);
    }

    public static void show(Teacher t) {
        t.eat(Value.v1);
    }

    public static void show(Person p) {
        p.eat(Value.v1);
    }

    public static void main(String[] args) {
        Student s = new Student();
        Teacher t = new Teacher();
        Person p = new Person();
        show(s);
        show(t);
        show(p);
    }
}
로그인 후 복사
이 접근 방식은 명백한 결함은 Person 클래스의 파생 클래스마다 밀접하게 관련된 메서드를 정의해야 하므로 코드가 많이 반복된다는 것입니다. 반면에 메서드 오버로드를 잊어버린 경우에는 오류가 보고되지 않습니다. 위 예의 세 가지 표시 방법을 하나로 결합할 수 있습니다. show(s)가 실행되면 출력 결과는 Student.eat()입니다. 이는 실제로 원하는 결과이지만 원하는 형식으로 실행되지 않는 것 같습니다. #🎜 🎜#
public static void show(Person p) {
     p.eat(Value.v1);
}
로그인 후 복사
로그인 후 복사
#🎜🎜 #Person 핸들을 받습니다. 쇼를 실행할 때 Person 핸들이 Teacher 객체 대신 Student 객체를 가리키는지 어떻게 알 수 있나요? 컴파일러는 다음에 설명된 바인딩 문제와 관련된 알 방법이 없습니다.

1. 메소드 호출 바인딩

메소드를 메소드 본문과 연결하는 것을 바인딩이라고 합니다. 실행하기 전에 바인딩을 수행하는 경우를 "초기 바인딩"이라고 합니다. 위의 예에서 Person 핸들이 하나만 있는 경우 컴파일러는 어떤 메서드를 호출할지 알 수 없습니다. Java는 런타임 중에 객체의 유형을 결정한 다음 해당 메소드를 호출할 수 있는 메소드 호출 메커니즘을 구현합니다. 런타임 중에 수행되며 객체의 유형을 기반으로 하는 이러한 바인딩을 동적 바인딩이라고 합니다. 메소드가 final로 선언되지 않는 한 Java의 모든 메소드는 동적으로 바인딩됩니다.

트레이스백 모양의 상속 관계를 나타내기 위해 그림을 사용합니다:

코드를 사용하여 다음과 같이 요약합니다: # 🎜🎜#

public static void show(Person p) {
     p.eat(Value.v1);
}
로그인 후 복사
로그인 후 복사
# 🎜🎜#상속 관계에 따르면 Circle은 Shape의 한 유형이므로 생성된 Circle 객체 핸들을 Shape에 할당하는 것이 적법합니다.

기본 클래스 메소드 중 하나가 호출되는 경우:

Shape s = new Shape();
로그인 후 복사
로그인 후 복사

이때 동적 바인딩으로 인해 Circle.draw()가 호출됩니다.

Shape s = new Shape();
로그인 후 복사
로그인 후 복사
Person은 Person에서 파생된 모든 클래스에 대한 공통 인터페이스를 설정했으며 모든 파생 클래스에는 먹고 말하기라는 두 가지 동작이 있습니다. 파생 클래스는 이러한 정의를 재정의하여 두 동작을 모두 재정의합니다.

메인 클래스에서 randPerson은 Person 객체의 핸들을 무작위로 선택합니다. **이의신청서 작성은 반품 명세서에서 이루어집니다. **return 문은 Boy 또는 Girl 핸들을 가져와 이를 Person 유형으로 반환합니다. 현재로서는 그것이 어떤 유형인지 알 수 없으며 Person 객체 핸들이라는 것만 알 수 있습니다.

메인 메소드에서 randPerson 메소드를 호출하여 Person 객체를 배열에 채워넣는데 구체적인 상황은 잘 모르겠습니다. 배열의 각 요소에 대한 eat 메소드가 호출될 때, 동적 바인딩의 역할은 객체의 재정의된 메소드를 실행하는 것입니다.

그러나 동적 바인딩에는 전제 조건이 있습니다. 바인딩 메서드는 기본 클래스에 있어야 합니다. 그렇지 않으면 컴파일되지 않습니다. Java의 상속에 대한 자세한 설명

class Person {
    void eat() {
        System.out.println("Person.eat()");
    }
}
class Boy extends Person {
    void eat() {
        System.out.println("Boy.eat()");
    }
    void speak() {
        System.out.println("Boy.speak()");
    }
}
public class Persons {
    public static void main(String[] args) {
        Person p = new Boy();
        p.eat();
        p.speak();  // The method speak() is undefined for the type Person
    }
}
로그인 후 복사

如果子类中没有定义覆盖方法,则会调用父类中的方法:

class Person {
    void eat() {
        System.out.println("Person.eat()");
    }
}
class Boy extends Person {
}
public class Persons {
    public static void main(String[] args) {
        Person p = new Boy();
        p.eat();
    }
}
로그인 후 복사

【运行结果】:
Person.eat()

2.静态方法的绑定

将上面的方法都加上static关键字,变成静态方法:

class Person {
    static void eat() {
        System.out.println("Person.eat()");
    }
    static void speak() {
        System.out.println("Person.speak()");
    }
}
class Boy extends Person {
    static void eat() {
        System.out.println("Boy.eat()");
    }
    static void speak() {
        System.out.println("Boy.speak()");
    }
}
class Girl extends Person {
    static void eat() {
        System.out.println("Girl.eat()");
    }
    static void speak() {
        System.out.println("Girl.speak()");
    }
}
public class Persons {
    public static Person randPerson() {
        switch ((int)(Math.random() * 2)) {
        default:
        case 0:
            return new Boy();
        case 1:
            return new Girl();
        }
    }
    public static void main(String[] args) {
        Person[] p = new Person[4];
        for (int i = 0; i < p.length; i++) {
            p[i] = randPerson();    // 随机生成Boy或Girl
        }
        for (int i = 0; i < p.length; i++) {
            p[i].eat();
        }
    }
}
로그인 후 복사

【运行结果】:

Person.eat() 
Person.eat() 
Person.eat() 
Person.eat()
로그인 후 복사

观察结果,对于静态方法而言,不管父类引用指向的什么子类对象,调用的都是父类的方法。

更多java相关文章请关注java基础教程栏目。

위 내용은 Java의 상속에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:cnblogs.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿