面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。封装可以被认为是一个保护屏障,防止该类代码和数据被其他类随意访问。要访问该类数据,必须通过指定的方式。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。
封装原则:将属性隐藏起来,若要访问某个属性,提供公共方法对其访问
封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
不使用封装的代码
要解决上面的设计缺陷,我们就可以使用封装.
生活中,我们要看电视,只需要按一下开关和换台就可以了.我们没有必要了解电视机内部结构.
隐藏对象内部的复杂性,只对外公开简单的接口,便于外界调用,从而提高系统的可扩展性、可维护性
我们程序设计要追求"高内聚、低耦合"
高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉
低耦合:仅暴露少量的方法给外部使用
封装的优点:
class Dog {
private String name = "旺财"; // 昵称
private int health = 100; // 健康值
private int love = 0; // 亲密度
private String strain = "拉布拉多犬"; // 品种
public int getHealth() {
return health;
}
public void setHealth (int health) {
if (health > 100 || health < 0) {
this.health = 40;
System.out.println("健康值应该在0和100之间,默认值是40");
} else
this.health = health;
}
// 其它getter/setter方法
}
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要
继承那一个类即可
其中,多个类可以称为子类,单独那一个类称为父类、超类(superclass) 或者基类。
继承描述的是事物之间的所属关系,这种关系是: is -a 的关系。
例如,图中狗 猫 人,哺乳动物属于动物。
可见,父类更通用,子类更具体。我们通过继承,可以使多种事物之间形成一种关系体系.
看如下这两个类图有什么问题?
使用继承优化后
类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模
提高代码的复用性!
我们在编写代码时候子类继承父类用到的关键字是 extends,它的中文意思是"扩展".子类是父类的扩展
对于被进程的类不同的叫法如下
超类、父类、基类、派生类
使用继承
class Pet{
//公共的属性和方法
}
class Penguin extends Pet{
//海豚继承了宠物类
//海豚特有的属性和方法
}
当子类需要访问父类中被子类覆盖的方法或属性时候,可以通过 super 关键字来实现
super 是直接父类对象的引用.
子类可以随意调用父类的普通方法,没有顺序限制.
任何类的构造函数中,若是构造函数的第一行代码没有显式 的调用 super(...),那么 Java 默认都会调用 super();作为父类的初始化函数.
public class Test {
public static void main(String[] args) {
new ChildClass().f();
}
}
class FatherClass {
public int value;
public void f(){
value = 100;
System.out.println
("FatherClass.value="+value);
}
}
class ChildClass extends FatherClass {
public int value;
public void f() {
super.f();
value = 200;
System.out.println
("ChildClass.value="+value);
System.out.println(value);
System.out.println(super.value);
}
}
super 总结
使用继承后效果
public class TestOverride {
public static void main(String[] args) {
Animal animal = new Animal();
animal.shout();
Dog dog = new Dog();
dog.shout();
}
}
class Animal{
void shout(){
System.out.println("发出声音! ");
}
}
class Dog extends Animal {
void shout(){
System.out.println("旺旺旺! ");
}
}
重写(小结)
构造方法也会被重写么?
方法重写规则
方法重载与重写区分
位置 | 方法名 | 参数表 | 返回值 | 访问修饰符 | |
---|---|---|---|---|---|
方法重写 | 子类 | 相同 | 相同 | 相同或是其子类 | 不能比父类更严格 |
方法重载 | 同类 | 相同 | 不相同 | 无关 | 无关 |
子类访问父类成员
访问父类构造方法
super(); //在子类构造方法中调用必须是第一句
super(name);
访问父类属性
super.name
访问父类方法
super.print()
public class TestExtends {
public static void main(String[] args) {
Mammal m1 = new Mammal();
m1.puru();
m1.eat();
}
}
class Animal {
String eyes="眼睛";
String name="无名";
public void eat(){
System.out.println("动物吃东西! ");
}
}
class Mammal extends Animal {
//哺乳
public void puru(){
eyes= "嘴巴";
System.out.println("小动物吃奶! ");
}
}
多态是继封装、继承之后,面向对象的第三大特性。
生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。
定义: 多态是指同一行为,具有多个不同表现形式.
多态性是 OOP 中的一个重要特性,主要是用来实现动态联编的,换句话说就是程序的最终状态只有在执行过程中才被决定而非在编译期间就决定了. 这对于大型系统来说提高系统的灵活性和扩展性至关重要.
使用多态的好处?
多态可以减少类中代码量,可以提高代码 的可扩展性和可维护性
引用变量的两种类型:(补充)
实现多态的两种方式
多态存在的三个必要条件:
多态实例代码:
class Animal {
int age=10;
public void shout(){
System.out.println("叫了一声! ");
}
}
class Dog extends Animal {
int age=28;
public void shout() {
System.out.println("旺旺旺! ");
}
public void gnawBone(){
System.out.println("我在啃骨头");
}
}
class Cat extends Animal {
int age=18;
public void shout() {
System.out.println("喵喵喵喵! ");
}
}
public class TestPolym {
public static void main(String[] args) {
Animal animal = new Dog(); //向上可以自动转型
System.out.println(animal.age); //属性调用时,仍然是基类的属性。属性没有多态!
// animal.shout();
animalCry(new Dog());
//传的具体是哪一个类就调用哪一个类的方法。大大提高了程序的可扩展性。
//如果没有多态,我们这里需要写很多重载的方法。如果增加一种动物,就需要重载一种动物的喊叫方法。非常麻烦。
//有了多态,只需要增加这个类继承Animal基类就可以了。
animalCry(new Cat());
Dog dog = (Dog) animal; //编写程序时,如果想调用运行时类型的方法,只能进行类型转换。不然通不过编译器的检查。
dog.gnawBone();
System.out.println(dog instanceof Animal);
System.out.println(animal instanceof Cat);
System.out.println(animal instanceof Dog);
}
static void animalCry(Animal a){
a.shout();
}
}