封装
Java中代码讲究 高内聚,低耦合
所谓高内聚,
以我的理解指的是类的内部数据操作细节自己完成,不允许外部干涉
低耦合
指的是仅对外暴露少量的方法用于使用
封装与隐藏
当我们创建一个对象以后,我们可以通过“对象.属性”的方式,对对象的属性进行值,这里,赋值操作要受到属性
的数据类型和存储范围的制约。除此之外,没有受到其他制约条件。但是,在实际问题中,我们往往需要给属性
赋值加入额外的限制条件。这个限制条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。
比如setLegs();
如下代码:
public void setLegs(int legs){
if(legs > 4){
this.legs = legs;
}else{
System.out.println("您设置的腿的个数有误");
}
}
同时我们需要避免用户再使用“对象,属性”的方式进行赋值,则需要将属性声明为private 私有的
private String name;
private int legs;
此时,针对于属性就体现了封装性
封装性的体现
我们将类的属性私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)
Java中修饰权限的修饰符有四种
可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
private 私有的
缺省(default),如果不写权限修饰符,则为默认
protected 被保护的
public 公共的
四种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
修饰类的话只能使用:缺省、public
总结:
Java提供了四种权限修饰符来修饰类及类的内部结构,体现类及类的内部结
构在被调用时的可见性的大小
继承
格式:
class Zi extends Fu{}
Zi: 子类 或者 派生类 或者 subclass
Fu: 父类 或者 超类 或者 基类 或者 superclass
extends: 延展,扩展
作用:
提高代码的复用性
便于功能的扩展
为之后的多态的使用,提供了前提
缺点:
增强了类与类之间的耦合性
规定:
只支持单继承和多重继承
一个类可以被多个子类继承:多重继承
一个类只能有一个父类:单继承
子父类是相对的概念
子类直接继承的父类叫直接父类,间接继承的父类称为:间接父类
子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法
注意:
如果我们没有显式的声明一个类的父类的话,则此类继承与java.lang.Object类
所有的java类(除java.lang.Object类之外)都直接或间接的继承于java.lang.Object类
意味着,所有的java类具有java.lang.Object类声明的功能
方法的重写:
方法的声明 权限修饰符 返回值类型 方法名 (形参列表)
约定俗成:子类中的叫重写的方法,父类中的叫被重写的方法
子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
子类重写的方法的权限修饰符**不小于**父类被重写的方法的权限修饰符
子类不能重写父类中 **private**修饰的方法
**返回值类型**
1.父类被重写的方法的返回值类型是void,则子类重写的方法是返回值类型只能是void
2.父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型是A类或A的子类
3.父类被重写的方法的返回值是基本数据类型,则子类重写的方法的返回值类型必须是相同的基本数据类型
4.子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声
明为static的(不是重写)
子类对象实例化的全过程:
从结果来看:继承性
子类继承父类以后,就获取了父类中声明的属性或方法
创建子类的对象,在堆空间中,就会加载所有父类中声明的属性
从过程来看:
当我们通过子类的构造器创建对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的
父类的构造器,直到调用到java.lang.Object类中空参的构造器为止。正因为加载过所有的父类的结构,
所以才可以看到内存中有父类中的结构子类对象才可以考虑进行调用
明确:
虽然创建子类的对象时,调用了父类的构造器,但是自始至终就创建了一个对象,即为new 的子类对象
多态
1.理解:可以理解为一个事物在不同时刻的多种形态
//猫可以看作为猫类,也可以看作为动物类
public class Animal{
//用protected修饰符,方便调用
protected String name;
protected int legs;
public void eat(){
System.out.println("动物觅食...");
}
}
//定义猫类,继承父类动物类
public class Cat extends Animal{
//重写父类的方法
@override
public void eat(){
System.out.println("猫吃鱼...");
}
//定义猫类特有的方法catch()
public void catch(){
System.out.println("猫抓老鼠...");
}
}
//定义狗类,继承父类动物类
public class Dog extends Animal{
//重写父类的方法
@override
public void eat(){
System.out.println("狗啃骨头...");
}
//定义狗类特有的方法houseKeeping()
public void houseKeeping(){
System.out.println("狗看家...");
}
}
2.何为多态性?
父类的引用指向子类的对象或者是子类的对象赋给父类的引用
public class AnimalTest{
public static void main(String[] args){
//创建猫类对象
//此时是当做猫类看
Cat cat = new Cat();
//此时是当做动物类看,这时叫做多态,
//向上转型:将Cat类型向上转为Animal类
Animal a = new Cat();
//调用eat()方法,此时的eat()方法是执行的猫类重写的eat()方法
a.eat();
}
}
3.多态的使用
有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是
子类重写父类的方法
总结:编译看左边,运行看右边
/*调用catch()方法,此时的catch()方法是执行的猫类特有的
catch()方法,但是,父类中并没有catch()方法,所以在编译时
找不到catch()方法,会报错,此时就需要instanceof关键字来判断
当前的对象变量是否是某个类型的对象
*/
//a.catch(); 编译报错
//判断当前的对象变量a是否是Cat类的对象
if(a instanceof Cat){
Cat cat = (Cat)a; //向下转型:将Animal类转为Cat类
cat.eat();
cat.catch();
}
4.多态性的使用前提:4.1 类的继承/实现关系 没有继承/实现就没有多态性
4.2 方法的重写
5.对象的多态性,只适用于方法,不适合属性(编译和运行都看左边)
原因:属性不能重写
多态为什么要向下转型?
因为有了多态以后,内存里也加载了子类特有的方法和属性,由于变量声明是父类类型,导致编译时只能
调用父类中声明的属性和方法,不能调用子类特有的方法和属性,所以向下转型