封装

在面向对象程式设计方法中,封装是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。

封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

简单的来说,就是将Java中的经常用到的代码进行封装起来,形成一个方法。比如,我们常用的实体类,使用private修饰变量,用于保护数据;对外提供getter和setter方法,用于调用。这就是一种典型的封装。

public class packagingTest {

    public static void main(String[] args) {
        User user=new User();
        //这里会报错,因为id和name是私有的,用于保护该数据
//        user.id=10;
//        user.name="张三";
        user.setId(1);
        user.setName("张三");
        System.out.println(user.getId());
        System.out.println(user.getName());
    }

}

class User{
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

結果:
1
张三

优点:
– 良好的封装能够减少耦合。
– 类内部的结构可以自由修改。
– 可以对成员变量进行更精确的控制。
– 隐藏信息,实现细节。

继承

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

继承的特性
– 子类拥有父类非private的属性,方法。
– 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
– 子类可以用自己的方式实现父类的方法。

继承主要目的是为了复用代码!简单的来说,就是将重复的代码抽出来,放到父类中,然后在再由子类继承使用,子类也是可以对父类进行扩展的。所以在继承关系中,可以这么理解,父类更通用,子类更具体。

打个比方,在动物世界中,猫和狮子是属于猫科,狗和狼是属于犬科。而它们也都是动物。猫和狮子有个共同的父类猫科,猫和狗有个共同的父类动物。所以它们是符合继承关系的, 只不过它们在行为上有所区别。猫和狗都有吃和睡,不过猫可以爬树,狗不可以。

public class extendTest {
    public static void main(String[] args) {
        Cat cat=new Cat();
        Dog dog=new Dog();
        cat.eat();
        cat.sleep("cat");
        cat.climbTree();
        dog.eat("dog");
        dog.sleep("dog");
    }
}
class  Animal{
    public void eat(String name){
        System.out.println(name+"正在吃东西...");
    }
    public void sleep(String name){
        System.out.println(name+"正在睡觉...");
    }
}
class Cat extends Animal{
    private String name="Cat";
    public void eat(){
        super.eat(name);
        System.out.println(name+"吃完了");
    }
    public void sleep(){
        this.sleep(name);
    }

    public void sleep(String name){
        System.out.println(name+"刚刚睡觉!");
    }

    public void climbTree(){
        System.out.println(name+"正在爬树!");
    }
}
class Dog extends Animal{

}

结果:
Cat正在吃东西...
Cat吃完了
cat刚刚睡觉!
Cat正在爬树!
dog正在吃东西...
dog正在睡觉...

代码解析:

在上述代码中,父类Animal实现了eat和sleep的方法,子类Cat和Dog使用了extends 关键字继承了父类Animal。子类Dog继承父类Animal之后什么都没做,而子类Cat不但继承了父类Animal,而且还增加了climbTree 方法,并且也重写了父类的eat和sleep方法。
在子类Cat中,出现了两个关键字:super和this。
这两个关键字的意义如下:

  • super关键字:实现对父类成员的访问,用来引用当前对象的父类。
  • this关键字:指向自己的引用。
    在上述代码中,子类Cat使用super关键字调用了父类Animal的eat方法,使用this关键字调用本类中的sleep方法。

说到继承,就不得不提这几个东西: final和protected修饰符、构造器、以及向上转型!
其中final和protected修饰符在这里就简单的描述下:

  • final:修饰的类不可以被继承。
  • protected:修饰的类仅对同一包内的类和所有子类可见。

构造器:
虽然子类可以继承父类的属性和方法(private修饰的除外),但是还有一样是子类无法继承的,那就是是构造器!对于构造器而言,它只能够被调用,而不能被继承。如果子类想使用父类的构造器,那么只需使用super关键字调用即可。

注:如果父类的构造器被private所修饰,那么是无法被外部调用的,包括子类!

向上转型:

将子类转换成父类,在继承关系上面是向上移动的,所以一般称之为向上转型。
之前的个例子中,猫和动物是属于继承关系,那么我们可以把猫当作动物就是向上转型!

public class extendTest {
    public static void main(String[] args) {
        Animal animal=new Cat();
        animal.eat("cat");
        animal.sleep("cat");
    }
}
class  Animal{
    public void eat(String name){
        System.out.println(name+"正在吃东西...");
    }
    public void sleep(String name){
        System.out.println(name+"正在睡觉...");
    }
}
class Cat extends Animal{
private String name="Cat";
    public void eat(){
        super.eat(name);
        System.out.println(name+"吃完了");
    }
    public void sleep(){
        this.sleep(name);
    }

    public void sleep(String name){
        System.out.println(name+"刚刚睡觉!");
    }

    public void climbTree(){
        System.out.println(name+"正在爬树!");
    }
}

结果:
cat正在吃东西...
cat刚刚睡觉!

上述代码中完成了向上转型,但是在向上转型中是存在着一些缺憾的,那就是属性和方法的丢失。例如上述代码中就丢失了Cat类中的climbTree()方法和name属性。所以慎用向上转型!

多重继承:
Java的继承是单继承,但是可以实现多重继承!
虽然一个子类只能继承一个父类,但是子类的子类也可以子类。
例如C类继承B类,B类继承A类,所以按照关系就是A类是B类的父类,B类是C类的父类。

继承的缺点:
虽然继承大大提升了代码的复用性,但是也提高了类之间的耦合性!父类更改,子类就必须更改!因此可以说继承破坏了封装,因为对于父类而言,它的实现细节对与子类来说都是透明的。
所以慎用继承!

多态

多态是指事物在运行过程中存在不同的状态。

多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。

使用多态的必要条件
– 要有继承关系;
– 子类要重写父类的方法;
– 父类引用指向子类对象,也就是向上转型。

多态使用的简单示例

在上面的继承讲解中,我们用到了猫和动物这两个之间的关系,这里我们也可以使用这,只需要稍微改下代码,就可以实现多态。

public class Test {
    public static void main(String[] args) {
        Animal animal=new Cat();
        animal.eat();
    }
}
class  Animal{
    private String name="Animal";
    public void eat(){
        System.out.println(name+"正在吃东西...");
        sleep();
    }
    public void sleep(){
        System.out.println(name+"正在睡觉...");
    }
}
class Cat extends Animal{
    private String name="Cat";
    public void eat(String name){
        System.out.println(name+"吃完了");
        sleep();
    }
    public void sleep(){
        System.out.println(name+"正在睡觉");
    }
}

结果:
Animal正在吃东西...
Cat正在睡觉

看到了运行结果之后,如果不熟悉多态的话,是不是感觉有些奇怪呢?
打印的第一句应该好理解,为什么打印的第二句不是Animal的方法,而是Cat中的方法呢?

我们知道多态是指事物在运行过程中存在不同的状态。而这里,我们用到了继承、重写以及向上转型。
在这里顺便提一下:

在向上转型中,一个父类的引用是可以指向多种子类对象,那么在运行时对于同一个消息是由实际的被引用的对象的类型来决定。

根据上述这段理解,我们再来看刚刚的那个示例。
在Cat类中,重写了父类Animal的sleep方法,并重载了eat方法。重载之后的eat(String name)方法和父类Animal的eat()方法不是同一个方法,因为是会在向上转型丢失的。而Cat子类重写了sleep方法,因此在向上转型的时候是不会丢失的,并且因为指定对对象的引用类型是Cat,所以Animal在调用eat()方法的时候,先是调用本类中eat()方法,然后在调用子类中的sleep()方法!

结论:

当父类引用指向子类方法时,必须调用那些父类中存在的方法,如果子类中对该方法进行了重写,那么在运行时就会动态调用子类中的方法,这就是多态。

使用多态的优点

  • 可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
  • 可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
  • 接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
  • 灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
  • 简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

淮城一只猫

永远年轻,永远热泪盈眶

发表评论

电子邮件地址不会被公开。 必填项已用*标注

我不是机器人*

EA PLAYER &

历史记录 [ 注意:部分数据仅限于当前浏览器 ]清空

      00:00/00:00