1.封装
封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装的好处:隐藏类的实现细节;让使用者只能通过程序员规定的方法来访问数据;可以方便的加入存取控制语句,限制不合理操作.
封装时的权限控制符区别如下:
1 /*
2 * 封装演示
3 */
4 public class Dog {
5 // 私有化属性
6 private String name;
7 private String sex;
8 private String color;
9
10 // 封装字段
11 public String getName() {
12 return name;
13 }
14
15 public void setName(String name) {
16 this.name = name;
17 }
18
19 public String getSex() {
20 return sex;
21 }
22
23 public void setSex(String sex) {
24 this.sex = sex;
25 }
26
27 public String getColor() {
28 return color;
29 }
30
31 public void setColor(String color) {
32 this.color = color;
33 }
34
35 }
Penguin类同理。
2.继承
语法:
修饰符SubClass extends SuperClass{
//类定义部分
}
在java中,继承通过extends关键字来实现,其中SubClass称为子类,SuperClass称为父类。修饰符如果是public,该类在整个项目中可见;不写public修饰符则该类只在当前包可用;不可以使用private和protected修饰符.
继承:是 java 中实现代码重用的重要手段之一.java中只支持单继承,即每个类只能有一个父类.继承表达的是 is a 的关系,或者说是一种特殊和一般的关系.
在java中,所有的java类都直接或间的接的继承了java.lang.long.Object类.Object类是所有java类的祖先.在定义一个类时,没有使用 extends 关键字,那么这个类直接继承Object类.
在java中,子类可以从父类中继承的有:
继承 public 和 protected 修饰的属性和方法,不管子类和父类是否在同一个包里.
继承默认权限修饰符修饰的属性和方法,但子类和父类必须在同一个包里.
子类无法继承父类的有:
无法继承 private 修饰的属性和方法
无法继承父类的构造方法
如果从父类继承的方法不能满足子类的需求,在子类中可以对父类的同名方法进行重写 ,以符合要求.
抽象出Dog类和Penguin类和父类Pet类(Pet类为抽象类,不能被实例化)
/**
* Dog和Penguin的父类Pet,而Pet对象是没有意义的,只是抽象出来的一个概念, 因此给Pet类添*
* 加abstract修饰符,让其成为一个抽象类,抽象不能被实例化.
* */
public abstract class Pet {
// 私有化属性
private String name;
private String sex;
// 封装字段
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
// 无参构造方法
public Pet() {
}
/**
* 有参构造方法
*
* @param name
* 名称
* @param sex
* 性别
* */
public Pet(String name, String sex) {
this.setName(name);
this.setSex(sex);
}
// Pet类的抽象方法eat(),抽象方法必需被子类重写
public abstract void eat();
// final修饰的方法不能被子类重写
public final void println() {
// 方法体…
}
}
// 狗继承动物类
class Dog extends Pet {
private String color;
// 封装字段
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
// 无参构造方法
public Dog() {
}
// 有参构造方法
public Dog(String name, String sex, String color) {
// 传参到父类的构造方法,此处不能用this.name = name.....
super(name, sex);
// 调用setColor()方法给属性color赋值
this.setColor(color);
}
// 重写父类eat()方法
public void eat() {
// 方法体....
}
}
// 企鹅继承动物类
class Penguin extends Pet {
private double weight;
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
// 重写父类eat()方法
public void eat() {
// 方法体….
}
}
// 测试类Test
class Test {
public static void main(String[] args) {
String name = "dog1";
String sex = "男";
String color = "red";
// 实例化对象
Dog dog = new Dog();
dog.setName(name); // 通过从父类处继承来的方法设置dog的属性name
dog.setSex(sex);
// 通过有参构造函数实例化对象
Dog dog1 = new Dog("dogName", "man", "black");
// 调用eat()方法,此方法被重写了
dog1.eat();
}
}
继承条件下构造方法调用规则如下
如果子类的构造方法中没有通过super显示调用父类的有参构造方法,也没有通过this显示调用自身的其他构造方法,则系统会默认先调用父类的无参构造 方法.在这种情况下写不写super()语句效果都是一样.
如果子类的构造方法中通过super显示调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法.
如果子类的构造方法中通过this显示调用自身的其他构造方法,在相应 构造方法中应用以上两条规则.
特别注意的是,如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行*父类Object类的无参构造方法为止.
abstract和final是功能相反的两个关键字,abstract可以用来修饰类和方法,不能用来修饰属性和构造方法.final可以用来修饰类,方法和属性,不能修饰构造方法.
3.多态
多态的三个条件:
1. 继承的存在(继承是多态的基础,没有继承就没有多态).
2. 子类重写父类的方法(多态下调用子类重写的方法).
3. 父类引用变量指向子类对象(子类到父类的类型转换).
子类转换成父类时的规则:
将一个父类的引用指向一个子类的对象,称为向上转型(upcastiog),自动进行类型转换.
此时通过父类引用调用的方法是子类覆盖或继承父类的方法,不是父类的方法.
此时通过父类引用变量无法调用子类特有的方法.
如果父类要调用子类的特有方法就得将一个指向子类对象的父类引用赋给一个子类的引用,称为向下转型,此时必须进行强制类型转换.
public class Person // 人类
{
String name;
int age;
public void eat() {
System.out.println("人们在吃饭!");
}
}
class Chinese extends Person {
// 重写父类方法
public void eat() {
System.out.println("中国人在吃饭!");
}
// 子类特有方法,当父类引用指向子类对象时无法调用该方法
public void shadowBoxing() {
System.out.println("练习太极拳!");
}
}
class English extends Person {
// 重写父类方法
public void eat() {
System.out.println("英国人在吃饭!");
}
}
// 测试类
class TestEat {
public static void main(String[] args) {
TestEat test = new TestEat();
// 引用指向中国人,创建中国人类对象
Person person1 = new Chinese();
// 此时调用的是Chinese的eat()方法
test.showEat(person1);
Person person2 = new English();
// 此时调用的是English的eat()方法
test.showEat(person2);
// 强制类型转换(向下转型)
Chinese chinese = (Chinese) person1;
// 向下转型后,调用子类的特有方法
chinese.shadowBoxing();
}
// 使用父类作为方法的形参,实现多态
public void showEat(Person person) {
// 传入的是哪具对象就调用哪个对象的eat()方法
person.eat();
}
}