目录
封装
高内聚,低耦合:封装细节,便于修改内部代码,提高可维护性。简化外部调用,便于调用者使用,便于扩展和协作。
开发中封装的简单规则
- 属性一般用private访问权限
属性私有后,提供相应的get和set方法来访问相关属性,这些方法通常是public修饰的,以提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头)
- 方法:一些只用于本类的辅助性方法可以用private修饰,希望被其他类调用的方法用public修饰。
javabean
javabean是一种Java语言写成的可重用组件,它是一个类。为写成javabean,类必须是具体和公共的,并具有无参构造器。
如果在a类里面设置了私有属性,在b类里面想要输出a类对象的私有属性的话,那么可以通过在a类里面设置public的、get方法。要不然是无法在其他类里面访问一个类的private属性的。
//javabean的封装演示
public class Person{
//属性一般用private修饰
private String name;
private int age;
private boolean flag;
//为属性提供public修饰的set/get方法
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public int getAge(){
return age;
}
public int setAge(int age){
this.age=age;
}
public boolean isFlag(){//注意Boolean类型的属性get方法是is开头的
return flag;
}
public void setFlag(boolean flag){
this.flag=flag;
}
}
javabean的编写要求
- 所有的javabean必须在一个包中(package)中。
- javabean必须生成public class,文件名与类名称相同。
- 所有属性必须封装,一个javabean不应该有公共实例变量,类变量都为private。
- 用于对属性赋值的方法叫做属性修改器或setter方法,用于读取属性值的方法成为属性访问器或getter方法。
- setter(getter)方法必须以小写的set(get)开头,后面加属性名,且属性名的第一个字母大写。(boolean类型的属性的getter方法是is加属性名,属性名首字母大写)
- javabean类必须有一个公共的无参构造器。
四个访问控制符
- private表示私有,只有自己类能访问.
- default表示没有修饰符修饰,只有同一个包的类能访问。(int a默认为default int a)
- protected表示可以被同一个包的类以及其他包中的子类访问。
注protected的两个细节:
- 若父类和子类在同一个包中,子类可访问父类的protected成员,也可以访问父类对象的protected成员。
- 若父类的子类不在同一个包中,子类可访问父类的protected成员,不能访问父类对象的protected成员。
多态
同一个方法的调用对于不同的对象有不同的行为,于是便有了多态。(传入的对象不一样,调用的方法也不一样)
多态的要点:
- 多态是方法的多态,不是属性的多态(多态与属性无关)
- 多态的存在有三个必要条件:继承,方法的重写,父类引用指向子类对象
- 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了
下面是使用多态和不使用多态来实现同一功能
使用多态的方法
public class Animimal{
public void shout(){System.out.println("叫了一声!");}
}
class Cat extends Animal{
public void shout(){System.out.println("喵喵喵!");}
}
class Dog extends Animal{
public void shout(){System.out.println("汪汪汪!");}
}
class Mouse extends Animal{
public void shout(){System.out.println("喵喵喵!");}
}
//在另外一个类里面进行测试
public class Test{
static void animalCry(Animal a){
a.shout(); //多态!!!
}
public static void main(String[] args){
Dog d =new Dog();
animalCry(d);
animalCry(new Cat());
}
}
//运行结果是
汪汪汪!
喵喵喵!
不使用多态的方法
public class Animimal{
public void shout(){System.out.println("叫了一声!");}
}
class Cat extends Animal{
public void shout(){System.out.println("喵喵喵!");}
}
class Dog extends Animal{
public void shout(){System.out.println("汪汪汪!");}
}
class Mouse extends Animal{
//没有对方法进行重写
}
}
//在另外一个类里面进行测试
public class Test{
static void animalCry(Dog a){
a.shout();
}
static void animalCry(Cat a){
a.shout();
}
static void animalCry(Mouse a){
a.shout();
}
//如果后面又新加了一个Animal的子类Tiger,那么程序员又需要在这里加一段代码,于是耦合性便增大了,十分的不方便。
public static void main(String[] args){
Dog d =new Dog();
animalCry(d);
animalCry(new Cat());
}
}
由上面的两个例子可以看出,使用多态方便了很多。如果没有使用多态,如果类的内部发生了改变,类的外面进行调用的时候也要跟着改变,太不灵活了,耦合性增强了。
对于多态,可以总结以下几点
- 使用父类类型的引用指向子类对象
- 该引用只能调用父类中定义的方法和属性
- 如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接,动态调用)
- 变量不能被重写(覆盖),“重写”的概念只针对方法,如果在子类重写了父类中的变量,那么在编译时会报错。
注意
- 编译通过只代表语法正确而已,但不代表程序能够跑起来。
- 多态的形式(向上转型)访问成员变量,编译和运行都是看等式左边。
- 多态的形式(向上转型)访问成员方法,编译看左边,运行看右边。
- 多态不能使用子类中特有的功能,但是多态中的向下转型可以帮我们实现。