面向对象之封装性

2020/3/17 8:01:23

本文主要是介绍面向对象之封装性,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

面向对象编程的三个特点

面向对象编程是比较符合人的认知思维的一种编程方式,比如提到机动车,我们会想到几个重要的属性:速度、轮子、载人等;还有几个重要的行为:加速、刹车、转弯等。
我们经常见到的出租车、救护车、公交车等都属于机动车的实际例子,如果执行“加速”,这些车都会增加前进的速度。
可以说,机动车属于具体实物中抽取出来共同的属性和行为,将其封装在一起,这在面向对象编程中称为封装性;而具体到出租车、救护车、公交车等,全部继承了机动车这些属性和行为,这在面向对象编程中称为继承性;同一个属性或行为,可能会产生不同的效果,比如公交车的载人量大于出租车,这在面向对象编程中称为多态性

封装性

将需要的属性(数据)和行为(对数据的操作,以下内容改称为方法)封装在一起,比如 Java 中“类”的概念,叫做面向对象的封装性。

封装方式

首先,按照惯例,如果类名使用字母,那么首字母大写;
其次,类的内容由两部分构成,属性与方法。作为类的成员,在声明属性与方法的时候,如果使用关键字 static 给予修饰,称为类成员(也称为静态成员),否则称为实例成员。实例成员按照访问权限细分,分为私有成员与公有成员。

ES6 的类

ES6 引入了类的概念,语法比较接近传统面向对象语言。

例子:

class Person {
    //公有属性
    name = "Tom";
    id = "232321";
    //公有方法
    getName() {
        return this.name;
    }

    //私有属性(提案中,暂无浏览器支持)
    #age = 20;
    //私有方法(提案中,暂无浏览器支持)
    #getAge() {
        return this.#age;
    }

    //静态属性(提案中,Chrome80 测试通过)
    static job = "IT";
    //静态方法
    static getJob() {
        return this.job;
    }
}

//未创建实例对象
//访问静态成员
console.log(Person.job); //输出:IT
console.log(Person.getJob()); //输出:IT
//访问公有成员
console.log(Person.id); //输出:undefined

//创建实例对象
let p1 = new Person();
//访问公有成员
console.log(p1.name); //输出:Tom
console.log(p1.getName()); //输出:Tom
//访问静态成员
console.log(p1.job); //输出:undefined

通过例子可以观察到:

1.公有成员只有在该类创建对象之后,才能访问,而静态成员只要该类被加载到内存中,就可以访问。
2.私有成员(暂无浏览器支持测试)与静态成员,在该类新创建的 p1 对象里访问不到;而类的公有成员可以访问到。

ES5 的组合封装

ES5 的组合封装是指:通过函数作用域的特性创建私有成员,通过 this 与构造函数原型创建公有成员,通过为构造函数定义属性和方法创建静态成员。

例子:

function Person() {
    //公有属性
    this.name = "Tom";
    this.id = "232321";
    //公有方法
    Person.prototype.getName = function() {
        return this.name;
    };

    //私有属性
    var age = 20;
    //私有方法
    var getAge = function() {
        return this.age;
    };
}
//静态属性
Person.job = "IT";
//静态方法
Person.getJob = function() {
    return this.job;
};

//未创建实例对象
//访问静态成员
console.log(Person.job); //输出:IT
console.log(Person.getJob()); //输出:IT
//访问公有成员
console.log(Person.id); //输出:undefined
//访问私有成员
console.log(Person.age); //输出:undefined

//创建实例对象
let p1 = new Person();
//访问公有成员
console.log(p1.name); //输出:Tom
console.log(p1.getName()); //输出:Tom
//访问静态成员
console.log(p1.job); //输出:undefined
console.log(Person.job); //输出:IT
//访问私有成员
console.log(p1.age); //输出:undefined

通过例子可以观察到:

私有成员与静态成员在该类新创建的 p1 对象里访问不到;而静态成员,无论该类有没有创建对象,都可以通过类名访问到。

利用闭包访问私有成员

闭包是有权访问另一个函数作用域中变量的函数,利用这一点,我们能够创建访问私有成员的特权方法。

例子:

function Person() {
    //私有属性
    var age = 20;

    //特权方法
    this.getAge = function() {
        return age;
    };
    this.setAge = function(value) {
        age = value;
    };
};

var p = new Person();
p.setAge(18);
console.log(p.getAge()); //输出:18

甚至可以直接将闭包作为创建实例对象的构造函数。

例子:

var Person = (function() {
    //私有属性
    var age = 20;

    //构造函数
    return function() {
        this.getAge = function() {
            return age;
        };
        this.setAge = function(value) {
            age = value;
        };
    };
})();

var p = new Person();
p.setAge(18);
console.log(p.getAge()); //输出:18

安全检测

鉴于构造函数只有在 new 关键字的作用下才会生成实例对象,因此检测构造函数的调用方式变得尤为重要。instanceof 以及 ES6 引入的 new.target 属性都可以用来做此类的安全检测。

例子:

function Person() {
    if (this instanceof Person) { //或者 new.target === Person
        this.name = "Tom";
    } else {
        return new Person();
    }
}

var p1 = new Person();
var p2 = Person();

如此一来,即使忘记了使用 new 关键字,仍然可以正确地创建实例对象。


如有错误,欢迎指正,本人不胜感激。

点击查看更多内容


这篇关于面向对象之封装性的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程