상속이란 기존 클래스에서 새로운 클래스를 파생시키는 것입니다. 새 클래스는 기존 클래스의 데이터 속성과 동작을 흡수하고 새로운 기능을 확장할 수 있습니다. 상속은 흔히 is-a 관계라고 합니다. 하위 클래스는 상위 클래스의 특성과 동작을 상속하므로 하위 클래스는 상위 클래스의 다양한 속성과 메서드를 갖습니다. 또는 하위 클래스가 상위 클래스의 메서드를 상속하여 하위 클래스가 상위 클래스와 동일한 동작을 갖도록 합니다.
예:
예를 들어 자동차에는 차체 크기, 색상, 스티어링 휠, 타이어라는 속성이 있으며 자동차와 트럭이라는 두 클래스가 자동차 클래스에서 파생됩니다. 자동차에 작은 백업을 추가하고 트럭에 큰 화물 상자를 추가합니다.
상속이 표현하는 것은 객체 클래스 간의 교차 관계입니다. 이를 통해 한 유형의 객체가 다른 유형의 객체의 데이터 멤버와 멤버 메서드를 상속할 수 있습니다. 클래스 B가 클래스 A를 상속하면 B에 속한 객체는 클래스 A의 속성(데이터 속성)과 기능(작업)의 전부 또는 일부를 갖게 됩니다. 상속된 클래스 A를 기본 클래스, 부모 클래스 또는 슈퍼 클래스라고 부릅니다. 그리고 우리는 그것을 기본 클래스, 부모 클래스 또는 슈퍼 클래스라고 부릅니다. 상속된 클래스 B는 A의 파생 클래스 또는 하위 클래스입니다.
상위 클래스와 하위 클래스를 나타내는 용어: 상위 클래스와 하위 클래스, 상위 클래스와 하위 클래스, 기본 클래스와 파생 클래스는 같은 의미입니다.
동물이 펭귄과 쥐인 동물 클래스를 개발하세요. 요구 사항은 다음과 같습니다.
펭귄: 속성(이름, ID), 메서드(먹기, 잠, 자기 소개)
쥐: 속성 (이름, 아이디) , 메소드 (먹기, 잠자기, 자기소개)
펭귄과 생쥐는 모두 동물입니다. 이렇게 하면 코드가 훨씬 간단해 질까요? 어떤 사람들은 이 속성을 작성하기 위해 두 개의 별도 클래스를 만들고 싶다고 말합니다. 하지만 그것은 마치 아버지가 당신에게 수백만 달러를 주었지만 당신이 그것을 원하지 않은 것과 같습니다. 직접 벌어야 했는데, 네가 이걸 하고 싶다면 나도 어쩔 수가 없어. Java는 상속을 제공하므로 이를 잘 활용해야 합니다. 이렇게 하면 개발 효율성이 크게 향상됩니다. 예를 들어 유지 관리가 향상되고 코드가 더 간결해지며 코드의 재사용성도 향상됩니다. 여러 번 사용할 수 있습니다. 동일한 코드를 여러 번 작성할 필요가 없습니다.)
1. 상속을 통해 중복 코드를 줄일 수 있습니다. 예를 들어, 상위 클래스에서 이미 제공한 메서드는 구현하지 않고도 하위 클래스에서 직접 사용할 수 있습니다.
2. 다형성의 전제조건은 상속입니다. 물론 상속을 사용하면 클래스 결합도 향상됩니다.
부모 클래스의 속성이 필요하지 않은 경우 원래 속성을 재정의할 수 있습니다.
상속은 단일 상속과 다중 상속으로 구분됩니다. 단일 상속은 하위 클래스가 최대 하나의 상위 클래스를 가질 수 있음을 의미합니다. 다중 상속은 하위 클래스가 두 개 이상의 상위 클래스를 가질 수 있음을 의미합니다. 다중 상속은 모호성을 가져올 수 있으므로 실제 응용에서는 단일 상속을 최대한 활용해야 합니다. Java 언어의 클래스는 단일 상속만 지원하는 반면 인터페이스는 다중 상속을 지원합니다. Java의 다중 상속 기능은 인터페이스를 통해 간접적으로 구현됩니다. 상속 구현
상속된 초기화 순서:
생성 방법이 있는 경우: 속성을 먼저 실행한 후 생성 방법을 실행합니다.
생성 방법에서 name 속성에 값이 할당되지 않은 경우 name 값은 클래스 속성에 할당된 값입니다.
extends 키워드
/*动物类*/ public class Animal { private String name; private int id; public Animal(String myName, String myid) { //初始化属性值 } public void eat() { //吃东西方法的具体实现 } public void sleep() { //睡觉方法的具体实现 } } /*企鹅是动物,所以可以继承动物类*/ public class Penguin extends Animal{ //企鹅继承了动物类,所以拥有了动物类的属性和方法 }
implements 키워드
public interface A { public void eat(); public void sleep(); } public interface B { public void show(); } public class C implements A,B { }
super 및 이 키워드
super 키워드: super 키워드를 사용하여 현재 객체의 상위 클래스를 참조하는 데 사용되는 상위 클래스 멤버에 액세스할 수 있습니다. 참고:
1. super 키워드는 생성자 또는 인스턴스 메서드 내에서만 사용할 수 있지만 정적 메서드 및 정적 코드 블록 내에서는 사용할 수 없습니다
2. 부모 클래스의 멤버 변수 및 메서드가 정의된 경우 개인 유형인 경우 상위 클래스의 비공개 유형 var 변수에 super.var 형식으로 액세스하려고 하면 컴파일 오류
가 발생합니다. 이 메서드가 현재 호출되고 있는 개체 참조입니다. 참고:
1. 오버로드된 생성자가 여러 개 있고 하나의 생성자가 이를 생성하기 위해 다른 생성자를 호출해야 하는 경우 이 (param) 형식을 사용하여 첫 번째 줄에서만 호출합니다.
2. 개체의 메서드가 개체의 다른 메서드를 호출해야 하는 경우 이를 기본 곡으로 사용하거나 실제로 작성할 필요가 없습니다.
3.当对象属性和方法中的局部变量名称相同时,在该方法中需要显式的使用this作为主调,以表示对象的属性,若不存在此问题,可以不显式的写this。
其实,其牵涉到的一个问题就是变量的查找规则:先局部变量 => 当前类中定义的变量 => 其父类中定义的可以被子类继承的变量 => 父类...
这块要完全理解需要看上面我写的“继承的初始化顺序”从这里可以看到程序是如何初始化的。
/** * 父类 * @author gacl * */ class FatherClass { public int value; public void f() { value=100; System.out.println("父类的value属性值="+value); } } /** * 子类ChildClass从父类FatherClass继承 */ class ChildClass extends FatherClass { /** * 子类除了继承父类所具有的valu属性外,自己又另外声明了一个value属性, * 也就是说,此时的子类拥有两个value属性。 */ public int value; /** * 在子类ChildClass里面重写了从父类继承下来的f()方法里面的实现,即重写了f()方法的方法体。 */ public void f() { super.f();//使用super作为父类对象的引用对象来调用父类对象里面的f()方法 value=200;//这个value是子类自己定义的那个valu,不是从父类继承下来的那个value System.out.println("子类的value属性值="+value); System.out.println(value);//打印出来的是子类自定义的那个value的值,这个值是200 /** * 打印出来的是父类里面的value值,由于子类在重写从父类继承下来的f()方法时, * 第一句话“super.f();”是让父类对象的引用对象调用父类对象的f()方法, * 即相当于是这个父类对象自己调用f()方法去改变自己的value属性的值,由0变了100。 * 所以这里打印出来的value值是100。 */ System.out.println(super.value); } } /** * 测试类 */ public class TestInherit { public static void main(String[] args) { ChildClass cc = new ChildClass(); cc.f(); } }
运行结果:
父类的value属性值=100
子类的value属性值=200
200
100
分析:
执行 ChlidClass cc = new ChlidClass();
首先在栈空间里面会产生一个变量cc,cc里面的值是什么这不好说,总而言之,通过这个值我们可以找到new出来的ChlidClass对象。由于子类ChlidClass是从父类FatherClass继承下来的,所以当我们new一个子类对象的时候,这个子类对象里面会包含有一个父类对象,而这个父类对象拥有他自身的属性value。这个value成员变量在FatherClass类里面声明的时候并没有对他进行初始化,所以系统默认给它初始化为0,成员变量(在类里面声明)在声明时可以不给它初始化,编译器会自动给这个成员变量初始化,但局部变量(在方法里面声明)在声明时一定要给它初始化,因为编译器不会自动给局部变量初始化,任何变量在使用之前必须对它进行初始化。
子类在继承父类value属性的同时,自己也单独定义了一个value属性,所以当我们new出一个子类对象的时候,这个对象会有两个value属性,一个是从父类继承下来的value,另一个是自己的value。在子类里定义的成员变量value在声明时也没有给它初始化,所以编译器默认给它初始化为0。即(父类的value为0,子类的value为0;)
执行第二句话: cc.f();
当new一个对象出来的时候,这个对象会产生一个this的引用,这个this引用指向对象自身。如果new出来的对象是一个子类对象的话,那么这个子类对象里面还会有一个super引用,这个super指向当前对象里面的父对象。所以相当于程序里面有一个this,this指向对象自己,还有一个super,super指向当前对象里面的父对象。
这里调用重写之后的f()方法,方法体内的第一句话:“super.f();”是让这个子类对象里面的父对象自己调用自己的f()方法去改变自己value属性的值,父对象通过指向他的引用super来调用自己的f()方法,所以执行完这一句以后,父对象里面的value的值变成了100。接着执行“value=200;”这里的vaule是子类对象自己声明的value,不是从父类继承下来的那个value。所以这句话执行完毕后,子类对象自己本身的value值变成了200。
위 내용은 Java 객체지향 상속의 예에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!