Java-8 面向对象(继承)
3.面向对象--继承
3.1继承概述
-
多个类中存在相同的属性和行为,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承这个新定义的类即可。
// 继承格式 class 子类名 extends 父类名{} // 被继承的类叫:父类,基类,超类 // 继承的类:子类,派生类 // java的继承只支持单继承(但支持多层继承), 父类中的私有成员是不能被继承的,构造方法不能被继承的,但是可以调用 Object称为所有类的祖先,如果一个类没有继承任何类,那么也默认继承Object
-
一个文件定义多个类:
- 只能有一个类使用public修饰,用public修饰的类必须和文件名相同。main方法也必须定义在这个类中,示例如下:
package demo; public class ExtendsDemo { public static void main(String[] args) { } } class Teacher{ } class Student{ }
- 但在实战开发时候,一般一个文件定义一个类
-
继承示例:
package ExtendsClass; public class ExtendDemo { public static void main(String[] args) { Teacher t = new Teacher(); System.out.println(t.age); } } class Person { String name; int age; char gender; public void eat() { System.out.println("开始吃饭"); } } // 继承Person class Teacher extends Person{ // 定义自己特有属性 double salary; } //继承Person class Student extends Person{ int score; }
3.2继承关系中属性赋值
package ExtendsClass;
public class ExtendDemo2 {
public static void main(String[] args) {
// 方式1
Worker w = new Worker();
w.setName("Tom");
w.setAge(21);
w.setGender('男');
w.setId("123");
// 方式2
Worker w2 = new Worker("222", "Lucy", 20, '男');
}
}
class People{
String name;
int age;
char gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
}
class Worker extends People{
String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Worker() {}
public Worker(String id, String name,int age,char gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.id = id;
}
}
3.3 this和super用法
- super:(父类中的对象)用于子类的成员和父类的成员重名时,super指代父类中的。
- this:(本类中的对象) 用于成员变量和局部变量重名,this指代的是成员变量。
- 在静态的方法中是不能使用this/super
- 调用成员:
- this.成员 -->成员变量,成员方法
- super.成员 -->成员变量,陈孤雁方法
- 调用构造方法:
- this(参数): 调用本类中的构造方法
- super(参数):调用父类中的构造方法
3.4继承中构造方法关系
- 子类中构造方法,会调用父类中无参构造方法。如果父类中没有无参的构造方法,系统会报错,我们必须直接或间接调用父类中其他构造方法。
package ExtendsClass;
public class ExtendDemo3 {
public static void main(String[] args) {
FatherClass f = new FatherClass();// 父类构造方法
SonClass f2 = new SonClass();//父类构造方法 子类构造方法
}
}
class FatherClass{
public FatherClass () {
System.out.println("父类构造方法");
}
}
class SonClass extends FatherClass{
public SonClass (){
System.out.println("子类构造方法");
}
}
- 直接调用父类带参构造方法
package ExtendsClass;
public class ExtendDemo3 {
public static void main(String[] args) {
// FatherClass f = new FatherClass();// 父类构造方法
SonClass f2 = new SonClass();//父类构造方法 子类构造方法
}
}
class FatherClass{
public FatherClass (int a) {
System.out.println("父类构造方法");
}
}
class SonClass extends FatherClass{
public SonClass (){
super(1);
System.out.println("子类构造方法");
}
public SonClass (int a){
super(a);
}
}
- 间接调用父类带参构造方法
package ExtendsClass;
public class ExtendDemo3 {
public static void main(String[] args) {
// FatherClass f = new FatherClass();// 父类构造方法
SonClass f2 = new SonClass();//父类构造方法 子类构造方法
}
}
class FatherClass{
public FatherClass (int a) {
System.out.println("父类构造方法");
}
}
class SonClass extends FatherClass{
public SonClass (){
this(1);
System.out.println("子类构造方法");
}
public SonClass (int a){
super(a);
}
}
-
注意: this() super() 调用构造方法时候,一定放在第一行。
-
练习
package ExtendsClass;
public class ExtendDemo4 {
public static void main(String[] args) {
FaClass f = new FaClass();
System.out.println(f.name);// Lucy
f.drink();// Lucy drink
Son1 s1 = new Son1();
System.out.println(s1.age);
}
}
class FaClass{
String name = "Lucy";
public void drink() {
System.out.println("Lucy drink");
}
// 无参构造方法
public FaClass() {
super();
}
// 为父类提供有参的构造方法,在子类构造方法中调用
public FaClass(int a) {
super();
}
}
class Son1 extends FaClass{
String name = "l1";
int age = 20;
public void drink() {
System.out.println("l1 drink");
}
// 显式调用无参构造方法
public Son1() {
super();
}
// 子类提供有参构造方法,显式调用本类中无参构造方法this();
public Son1(int a) {
this();
}
// 为子类提供无参构造方法,显式调用父类构造方法
public Son1(String s) {
super();
}
}
class Son2 extends FaClass{
String name = "l2";
public void drink() {
System.out.println("l2 drink");
}
// 为父类提供有参的构造方法,在子类构造方法中调用
public Son2() {
super(22);
}
}
3.5继承中成员方法的关系
- 先在子类中找成员方法,子类中没有去父类中找成员方法,父类中没有则报错。
package jc;
public class ExtendDemo {
public static void main(String[] args) {
Teacher t = new Teacher();
t.sleep();// teacher sleep
}
}
class Person{
public void sleep( ) {
System.out.println("person sleep");
}
}
class Teacher extends Person{
public void sleep() {
System.out.println("teacher sleep");
}
}
上面相当于方法的重写,它的定义是子类中出现了和父类中的方法名,参数列表,返回值类型都一样的方法,它就叫做方法重写。
- 通过@Override注解,验证是否符合方法重写规范。
class Teacher extends Person{
@Override
public void sleep() {
System.out.println("teacher sleep");
}
}
-
注意事项:
- 父类中私有方法不能被重写 private修饰的。 (虽然子类可以与父类相同的私有方法,但那不叫方法的重写)
- 子类重写父类方法,访问权限不能更低。(如父类的方法用public修饰,子类中重写方法的修饰符要大于等于父类中方法)
- 父类中静态方法,也必须写静态方法。(静态方法不能重写,它不具备多态的特征)
-
继承练习:判断一个坐标是否在当前区域内
// Rect.java
package com.xjk;
public class Rect {
double width;
double height;
public Rect(double width, double height) {
this.width = width;
this.height = height;
}
// 构造方法
public Rect() {
width = 10;
height = 10;
}
public double perimeter() {
return 2*(width+height);
}
public double area() {
return width*height;
}
}
// PlainRect.java
package com.xjk;
public class PlainRect extends Rect {
double startX;
double startY;
public PlainRect(double width,double height, double startX, double startY) {
this.height = height;
this.width = width;
this.startX = startX;
this.startY = startY;
}
public PlainRect() {
height = 0;
width = 0;
startX = 0;
startY = 0;
}
public boolean isInside(double x, double y) {
if (x >=startX&&x<=(startX+width)&&y<=startY&&y>=(startY-height)) {
return true;
}else {
return false;
}
}
}
// RectDemo.java
package com.xjk;
public class RectDemo {
//
public static void main(String[] args) {
PlainRect pr = new PlainRect(20,10,10,10);
System.out.println("周长为:" + pr.perimeter());
System.out.println("面积为:" + pr.area());
boolean re = pr.isInside(25.5, 13);
if (re){
System.out.println("在矩形范围内");
} else {
System.out.println("不在矩形范围内");
}
}
}