本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Java三大特征(封装/继承/多态)
1、封装
封装的好处:
- 隐藏信息(权限),提供特定方法访问
- 方便加入控制语句
- 方便修改实现
封装的具体表现:
-
属性用private修饰
-
方法用public修饰
package JavaSE.JavaOOP.fz;
public class Book {
/*
私有化属性
*/
private String name;//书名
private String author;//作者
private double price;//定价
private char ch ;//
private Book(){}//私有化构造方法
/*
public 方法 访问私有属性
*/
//获取Book类的对象
public static Book getBookObject(){
if(book==null){
book=new Book();
}
return book;
}
//修改定价
public void setPrice(double p){
price=p;
}
//获取定价
public double getPrice(){
return price;
}
//修改书名
public void setName(String n){
if(n.length()<20&&n.length()>0){
name=n;
}
}
//获取书名
public String getName(){
return name;
}
//修改作者
public void setAuthor(String author){
if(a.length()<15&&a.length()>0){
this.author=author;
}
}
//获取作者
public String getAuthor(){
return author;
}
//出版情况
public void publish(){
if(name!=null){
System.out.println(name+"已出版");
}
else{
System.out.println("未出版");
}
}
//显示书本各种信息
public void display(){
System.out.println("书名:"+name+"\r\n作者:"+author+"\r\n定价:"+price);
System.out.println(name+"已出版\r\n");
}
}
package JavaSE.JavaOOP.fz;
//测试例
public class test1 {
//单例模式:在程序中运行过程中,只创建一个对象
public static void main(String[] args) {
Book b = Book.getBookObject();//通过方法来实例化对象
b.setAuthor("孙武");//设置作者
b.setName("孙子兵法");//设置书名
b.setPrice(36.8);//设置定价
b.display();//显示信息
}
}
运行结果:
this关键字
- this关键字代表自身类的对象
-
使用this关键字引用成员变量
-
使用this关键字引用成员方法
-
当方法中参数与与成员变量重名
使用this区分
-
引用构造方法
注意:this关键字必须放在非静态方法里面
super() 从子类中调用父类的==构造==方法,this() 在同一类内调用其它方法
package JavaSE.JavaOOP.Packaging;
public class China {
/* private 修饰属性 */
private String province;//省份
private String national;//民族
/*
public 修饰方法
*/
public China(){//无参构造方法
System.out.println("China-->无参构造方法");
}
public China(int i){//有参构造方法
System.out.println("China-->有参构造方法");
}
//设置省份
public void setProvince(String province){
this.province=province;
//形参与变量重名时用this区分,this.变量名表示成员变量
}
//设置信息
public void setInfo(String national){
this.setProvince(province);//用this调用其他方法
this.national=national;
}
//获取信息
public void getInfo(){
System.out.println(province);
System.out.println(national);
}
}
package JavaSE.JavaOOP.Packaging;
public class ChinaTest {
public static void main(String[] args) {
China c=new China();//创建对象
c.setProvince("Shaanxi");//设置身份
c.setInfo("汉");//设置民族
c.getInfo();//获取信息
}
}
运行结果:
2.继承
继承:从已有类派生出新类,新类拥有父类的所有非私有成员变量和成员方法.
Java中所有类都直接或间接继承了Object类
何时使用继承?
动物:
猫,狗,猪,羊
书本:
纸质书
电子书
继承体现的关系:" is a "
继承是为了提升代码的复用性,节约成本
而不是为了继承而继承
当A类和B类符合,A是B的一种或B是A的一种,此时可以用继承
Java中只支持单继承,而不支持多继承,如图
package Test.extendsdemo;
//public class People extends Object
//Object类是Java中所有类的基类(超类)
//父类
public class People {
//私有属性(子类无法访问)
private String name;
private int age;
//公共方法 公共及构造方法都可继承
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;
}
void sleep(){
System.out.println("睡觉");
}
//构造器
//无参构造
public People() {
System.out.println("父类无参构造");
}
//带参构造
public People(String name, int age) {
this.name = name;
this.age = age;
}
}
//子类
class Student extends People{
/*
重写/覆盖 override
当父类方法不满足子类的需求,子类可重写父类方法
注意:1静态方法/构造方法/成员变量 不能重写
2重写父类方法,须结构一致(参数列表,方法名,返回值)
3对于子类重写方法,访问权限修饰符:子类 >= 父类
*/
private String xuehao;
//构造器
//无参
public Student(){
/*
当创建一个子类对象时,会在子类构造方法中调用父类构造方法(先初始化父类成员)
子类构造方法默认第一句调用super()为父类变量赋值初始化
*/
System.out.println("子类无参构造");
}
//有参
public Student(String name, int age, String xuehao) {
super(name, age);
/*
显式调用super(),必须在子类构造方法第一句
使用super()传参,调用指定的构造方法
*/
this.xuehao = xuehao;
}
//子类重写父类方法
@Override
//java 中的 注解标签 :覆盖,重写
// 写了@Override,在编译过程中不符合规范时报错
@Override
public void sleep() {
System.out.println("学生睡觉");
}
//子类特有方法
public void learn(){
System.out.println("学生学习");
}
}
super:
在调用子类对象构造方法中
默认super()先调用 父类的无参构造方法 super()必须在第一句
也可显式调用
package Test.extendsdemo;
//测试例
public class PeopleTest {
public static void main(String[] args) {
People p=new People("Tom",21);
Student s = new Student("Danny",21,"s1001");
p.setName("Tony");//修改名字
System.out.println(p.getName());//输出名字
p.sleep();
//父类方法
s.setAge(31);//修改年龄
System.out.println(s.getAge());//获取年龄
s.sleep();
s.setXuehao("s1010");//修改学号
System.out.println(s.getXuehao());//获取学号
s.learn();
}
}
运行结果:
3.多态
同一事物在不同时刻表现不同状态
同一个接口,使用不同的实例而执行不同操作 (如)
多态存在的必要条件: 1.继承 2.方法重写(抽象类) 3.父类引用指向子类对象 三者缺一不可
使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
我们在原来例子上稍加修改,上个例子中有继承,重写,现在我们在测试例中将父类引用指向子类对象即可
package Test.extendsdemo;
//public class People extends Object
//Object类是Java中所有类的基类(超类)
//父类
public class People {
//私有属性(子类无法访问)
private String name;
private int age;
String s="People";//非私有属性
//公共方法 公共及构造方法都可继承
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;
}
void sleep(){
System.out.println("睡觉");
}
//父类静态方法
public static void staticTest(){
System.out.println("People静态方法");
}
//构造器
//无参构造
public People() {
System.out.println("父类无参构造");
}
//带参构造
public People(String name, int age) {
this.name = name;
this.age = age;
}
}
//子类
class Student extends People{
/*
重写/覆盖 override
当父类方法不满足子类的需求,子类可重写父类方法
注意:1静态方法/构造方法/成员变量 不能重写
2重写父类方法,须结构一致(参数列表,方法名,返回值)
3对于子类重写方法,访问权限修饰符:子类 >= 父类
*/
private String xuehao;
String s="Student";
//构造器
//无参
public Student(){
/*
当创建一个子类对象时,会在子类构造方法中调用父类构造方法(先初始化父类成员)
子类构造方法默认第一句调用super()为父类变量赋值初始化
*/
System.out.println("子类无参构造");
}
//有参
public Student(String name, int age, String xuehao) {
super(name, age);
/*
显式调用super(),必须在子类构造方法第一句
使用super()传参,调用指定的构造方法
*/
this.xuehao = xuehao;
}
//子类重写父类方法
@Override
//java 中的 注解标签 :覆盖,重写
// 写了@Override,在编译过程中不符合规范时报错
@Override
public void sleep() {
System.out.println("学生睡觉");
}
//子类重写父类静态方法
public static void staticTest(){
System.out.println("Student静态方法");
}
//子类特有方法
public void learn(){
System.out.println("学生学习");
}
}
package Test.extendsdemo;
//测试例
public class PeopleTest {
public static void main(String[] args) {
People p = new Student();//父类引用子类对象
p.sleep();//公共方法
/*
多态访问类中成员,
编译期间调用父类方法,运行期间执行子类:编译看左边,运行看右边
对于静态方法和属性,编译与运行都看左边
*/
p.staticTest();//静态方法
System.out.println(p.s);//属性
}
}
我们将People 类的引用 p指向了Student对象,在使用p调用方法时,可以看到只能调用父类People的方法
运行看一下结果:
可以看到构造方法和sleep方法都执行了子类的,子类构造方法中又默认先调用父类构造方法
而静态方法和属性却访问父类的
形如People p = new Student(); 称为向上转型
向上转型的父类引用只能调用父类方法,执行子类方法
想让父类也能调用子类方法,必须要向下转型
多态的实现方法
-
重写
-
抽象方法和抽象类
-
接口
我们这里只用了一般的重写来实现多态,下一篇文章详细介绍抽象类与接口,并用它们实现多态