第六章 封装和继承
面试题
1、描述一下封装、继承
2、构造方法的特点
3、什么是方法重载?
1、封装
属性的封装,可以提高安全性
属性的封装
步骤:
1、字段私有化
2、提供公共接口(方法) 读取getter、写入setter
getter就是get方法,返回值为某一字段值的方法
setter就是set方法,无返回值,可通过传入参数给某字段(属性)赋值
public class Book { private String bookName; private String writer; private int price; public Book(){}; public Book(String bookName,String writer,int price) { this.price=price; this.bookName=bookName; this.writer=writer; } public Book(StringBuffer bookName,StringBuffer writer,int price) { this.price=price; this.bookName=bookName.toString(); this.writer=writer.toString(); } public void setBookName(String bookName) { this.bookName = bookName; } public String getBookName() { return bookName; } public void setPrice(int price) { this.price = price; } public int getPrice() { return price; } public void setWriter(String writer) { this.writer = writer; } public void setWriter(StringBuffer writer) { this.writer = writer.toString(); } public String getWriter() { return writer; } public int upPrice() { return this.price*2; } public int upPrice(int a) { if (a==3) { this.price = this.price * 3; return this.price; } else return this.price; } public void show() { System.out.println("书名"+this.bookName+"\t价格"+this.price+"\t作者"+this.writer); } }
public class Prac4 { public static void main(String[] args) { Book book=new Book(); Book book1=new Book("海底两万里","无名氏",56); StringBuffer sbfName=new StringBuffer("从百草园到三味书屋"); StringBuffer sbfWriter=new StringBuffer("鲁迅"); Book b2=new Book(sbfName,sbfWriter,23); b2.setWriter("高尔基"); b2.setWriter(sbfWriter); book1.upPrice(); book1.upPrice(3); b2.show(); book1.show(); } }
2、构造方法
创建对象时需要依次对各属性赋值,调用setter方法,比较繁琐。
故引入构造方法。可在对象创建时完成对属性的赋值(初始化)
构造方法特点
1、方法名和类名一致
2、没有返回值类型
3、在创建对象时调用,new 构造方法(参数) 不能显式调用
public Book(String bookName,String writer,int price) { this.price=price; this.bookName=bookName; this.writer=writer; } public Book(){ }
1、当未编写构造方法时,系统提供默认的无参构造方法
2、一旦定义了带参的构造方法,那么无参构造方法就会被覆盖。
若要使用无参构造,则需要再次定义。
3、方法重载
1、同一个类中有多个同名方法(返回值类型相同)
2、参数不同(参数的个数不同、类型不同或者顺序不同)
符合以上两点称为方法重载
由此可以引出:构造方法重载、get和set方法重载。只要是方法就能重载。
public void setWriter(String writer) { this.writer = writer; } public void setWriter(StringBuffer writer) { this.writer = writer.toString(); } public int upPrice() { return this.price*2; } public int upPrice(int a) { if (a==3) { this.price = this.price * 3; return this.price; } else return this.price; }
好处:
1、无需定义不同名字的方法
2、调用方法时,会根据参数的不同,自动调用适合的方法。
4、继承
4.1 概念
继承:子承父业;
需求:人类、学生类、教师类
1、代码冗余;(重复)
2、如何实现代码重用
3、扩展父类的功能
名词:
父类:超类,基类;如何设计:共性的属性和方法,提炼到父类中
子类:派生类;设计独有的属性和方法
4.2 特点
继承:
关键字:extends
语法:子类 extends 父类
定义:子类能够继承父类中非私有的属性和方法,不能继承构造方法,可以增加自己独有的属性和方法
不能被继承的:private修饰的属性或方法,构造方法
特点:
1、 单根性,只能有一个父类
2、传递性:A extends B ; B extends C
满足一个关系才能使用继承:is---a关系
注意:final修饰的类不能被继承,例如:String类
优点:
1、减少代码冗余
2、实现代码重用
3、扩展父类功能
4.3构造方法在继承中的关系
子类对象的实例化需要先实例化父类对象
1、子类会默认调用父类的无参构造方法进行实例化,父类需要提供无参的构造方法;
2、子类可以通过super关键字指定调用父类的某一个构造方法进行实例化
public Student(){ //调用父类的构造方法,必须放在第一行 super("李四"); System.out.println("Student()"); }
示例:
1、人类:学生、教师
2、动物类:狗、猫
3、汽车类:卡车、轿车
4.4 object类
是所有类的祖先类
java中所有类都继承自:object类
4.5方法重写
在有继承关系的类中:
在子类中提供一个跟父类中的方法(原型)相同的方法
重写父类方法需要满足的条件,方法名相同:
1、子类方法的可访问性大于或者等于父类方法的可访问性
2、子类方法的返回值类型与父类中被重写方法的返回值类型一致(或者是子类)
3、子类方法参数列表应该和被重写的方法保持一致
public class SmallStudent extends Student { public void play(){ System.out.println("小学生在玩耍"); } //覆盖 重写 @Override public Student study(){ System.out.println("小学生在看图学习"); return null; } //借助于编译器进行语法检查:确保符合重写的要求 @Override public String toString() { return "名字:"+super.getName()+"年龄:"+super.getAge()+"性别:"+super.getSex(); } @Override public boolean equals(Object obj) { //将对象的比较换成对名字的比较 SmallStudent smallStudent= (SmallStudent) obj; return this.getName().equals(smallStudent.getName()); } }
4.6 继承中的静态和非静态
父类中的可继承的静态属性和方法,直接被子类继承;如果子类中有相同的属性和方法,会隐藏父类中的同名属性和方法
父类中可继承的非静态属性,直接被子类继承;如果子类中有相同的属性的话,会隐藏父类中的同名属性
父类中的非静态方法可以被子类的方法重写
4.7补充:
静态属性、方法和代码块
静态代码块
//静态代码块 static { System.out.print("静态代码块"); }
第一次加载类时调用,只调用一次
实例代码块:
//实例代码块 { System.out.print("实例代码块"); }
每创建一次对象,就调用一次,在构造方法之前调用。
执行过程:
静态代码块--->静态属性、方法------>实例代码块---->构造方法