Java三大特征-继承,封装,多态
继承的定义?
继承是以已存在的类的定义为基础建立新类的技术,新类的定义可以增加新数据或新功能,也可用父类的功能,但不能选择性地继承父类
同时在使用继承时需要记住三句话:
1、子类拥有父类非private的属性和方法。
2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
3、子类可以用自己的方式实现父类的方法。
讲到继承一定少不了这三个东西:构造器、protected关键字、向上转型。
构造器
对于构造器而言,它只能够被调用,而不能被继承。 调用父类的构造方法我们使用super()即可。
public class Person { protected String name; Person(){ System.out.println("Person Constrctor..."); } } public class Husband extends Person{ private Wife wife; Husband(){ System.out.println("Husband Constructor..."); } public static void main(String[] args) { Husband husband = new Husband(); } } Output: Person Constrctor... Husband Constructor...
结论:父类有默认构造器时,编译器会默认给子类调用父类的构造器。
public class Person { protected String name; Person(String name){ System.out.println("Person Constrctor-----" + name); } } public class Husband extends Person{ private Wife wife; Husband(){ super("chenssy"); System.out.println("Husband Constructor..."); } public static void main(String[] args) { Husband husband = new Husband(); } } Output: Person Constrctor-----chenssy Husband Constructor...
结论:如果父类没有默认的构造器,子类必须显示的指定父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)
protected关键字
尽管可以使用protected访问修饰符来限制父类属性和方法的访问权限,但是最好的方式还是将属性保持为private(我们应当一致保留更改底层实现),通过protected方法来控制类的继承者的访问权限。
向上转型
问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则必要继承,如果不需要,应好好考虑是否需要继承。
继承存在如下缺陷:
1、父类变,子类就必须变。
2、继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的。
3、继承是一种强耦合关系。
封装的定义?
即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(功能)结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。
封装的好处?
如果需要修改Husband,比如将age属性改为String类型?只有一处使用这个类还好,如果有很多处那要改到崩溃。如果使用封装,我们可以不需要做任何修改,只需要改变下Husband类的setAge()方法即可。
public class Husband { /*对属性的封装*/ private String age ; //改成 String类型 public String getAge() { return age; } public void setAge(int age) { //转换即可 this.age = String.valueOf(age); } }
其他的地方依然那样引用(husband.setAge(22))保持不变。
到了这里我们可以看出,封装确实可以使我们容易地修改类的内部实现,而无需修改使用了该类的客户代码。
我们再看这个好处:可以对成员变量进行更精确的控制。
还是那个Husband,一般来说我们在引用这个对象的时候是不容易出错的,但是有时手快,比如人的年龄设置成300:
Husband husband = new Husband(); husband.setAge(300);
使用封装我们就可以避免这个问题,我们对age的访问入口做一些控制(setter)如:
public class Husband { private int age ; public int getAge() { return age; } public void setAge(int age) { if(age > 120){ System.out.println("ERROR:error age input...."); //提示錯誤信息 }else{ this.age = age; } } }
上面都是对setter方法的控制,通过使用封装也能够对对象的出口做很好的控制。比如我们在数据库中一般都是已1、0方式来存储性别的,但是在前端我们又不能展示1、0,这时我们只需要在getter()方法里面做一些转换即可。
public String getSexName() { if("0".equals(sex)){ sexName = "女"; }else if("1".equals(sex)){ sexName = "男"; }else{ sexName = "空"; } return sexName; }
多态的定义?
多态性是允许你将父对象设置成为一个或多个他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说就是,允许将子类类型的指针赋值给父类类型的指针,把不同的子类对象都当作父类来看。
多态分类
编译时多态:比如重载
运行时多态:比如重写
Java 实现多态有 3 个必要条件:
一、要有继承;
二、要有重写;
三、父类引用指向子类对象。
多态中成员的特点
1.多态成员变量:编译看左边,运行看左边
Fu f=new Zi();
System.out.println(f.num);//f是Fu中的值,只能取到父中的值
2.多态成员方法:编译看左边,运行看右边
Fu f=new Zi();
System.out.println(f.show());//f的门面类型是Fu,但实际类型是Zi,所以调用的是重写后的方法。
instanceof关键字
作用:用来判断某个对象是否属于某种数据类型,返回类型为布尔类型
Fu f1=new Zi(); Fu f2=new Son(); if(f1 instanceof Zi){ //f1实例对象 Zi类型 System.out.println("f1是Zi的类型"); } else{ System.out.println("f1是Son的类型"); }
多态的转型
多态的转型分为向上转型和向下转型两种
向上转型:多态本身就是向上转型过的过程
使用格式:父类类型 变量名=new 子类类型();
适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。
向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用类型转为子类引用各类型
使用格式:子类类型 变量名=(子类类型) 父类类型的变量;
适用场景:当要使用子类特有功能时。
多态案例:
例1:(理解多态,可以重点看这个案例)
public class demo04 { public static void main(String[] args) { People p=new Stu(); p.eat(); //调用特有的方法 Stu s=(Stu)p; s.study(); } } class People{ public void eat(){ System.out.println("吃饭"); } } class Stu extends People{ @Override public void eat(){ System.out.println("吃水煮肉片"); } public void study(){ System.out.println("好好学习"); } } class Teachers extends People{ @Override public void eat(){ System.out.println("吃樱桃"); } public void teach(){ System.out.println("认真授课"); } }
运行结果:吃水煮肉片 好好学习