日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python封装继承多态_浅谈JavaScript的面向对象和它的封装、继承、多态

發布時間:2023/12/20 python 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python封装继承多态_浅谈JavaScript的面向对象和它的封装、继承、多态 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫在前面

既然是淺談,就不會從原理上深度分析,只是幫助我們更好地理解...

面向對象與面向過程

面向對象和面向過程是兩種不同的編程思想,剛開始接觸編程的時候,我們大都是從面向過程起步的,畢竟像我一樣,大家接觸的第一門計算機語言大概率都是C語言,C語言就是一門典型的面向過程的計算機語言。

面向過程主要是以動詞為主,解決問題的方式是按照順序一步一步調用不同的函數。

面向對象是以名詞為主,將問題抽象出具體的對象,而這個對象有自己的屬性和方法,在解決問題的時候,是將不同的對象組合在一起使用。

//面向過程裝大象

1.開(冰箱)

2.(大象)裝進(冰箱)

3.關(冰箱)

//面向對象裝大象

1. 冰箱.開門()

2. 冰箱.裝進(大象)

3. 冰箱.關門()

從這個例子可以看出,面向對象是以主謂為主,將主謂堪稱一個一個的對象,然后對象有自己的屬性和方法。

面向對象是以功能來劃分問題的,而不是步驟。功能上的統一保證了面向對象設計的可擴展性,解決了代碼重用性的問題。

這也是在漫長的程序設計的發展過程中得到的驗證結果,面向對象的編程思想較之于面向過程較好一點

封裝

面向對象有封裝、繼承和多態三大特性。

封裝:就是把事物封裝成類,隱藏事物的屬性和方法的實現細節,僅對外公開接口。

在ES5中,并沒有class的概念,但是由于js的函數級作用域(函數內部的變量函數外訪問不到)。所以我們可以模擬class。在es5中,類其實就是保存了一個函數的變量,這個函數有自己的屬性和方法。將屬性和方法組成一個類的過程就是封裝。

1.通過構造函數添加

JavaScript提供了一個構造函數(Constructor)模式,用來在創建對象時初始化對象。構造函數其實就是普通的函數,只不過有以下的特點

①首字母大寫(建議構造函數首字母大寫,即使用大駝峰命名,非構造函數首字母小寫)

②內部使用this

③使用new生成實例

通過構造函數添加屬性和方法實際上也就是通過this添加的屬性和方法。因為this總是指向當前對象的,所以通過this添加的屬性和方法只在當前對象上添加,是該對象自身擁有的。所以我們實例化一個新對象的時候,this指向的屬性和方法都會得到相應的創建,也就是會在內存中復制一份,這樣就造成了內存的浪費。

function Cat(name,color){

this.name = name;

this.color = color;

this.eat = (() => {

console.log("fish!")

})

}

//生成實例

var cat1 = new Cat("tom", "gray")

通過this定義的屬性和方法,我們實例化對象的時候斗湖重新復制一份

2.通過原型prototype封裝

在類上通過this的方式添加屬性和方法會導致內存浪費的現象,有什么辦法可以讓實例化的類所使用的屬性和方法 直接使用指針 指向同一個屬性和方法。

這就是原型的方法

JavaScript規定,每一個構造函數都有一個prototype屬性,指向另一個對象。這個對象的所有屬性和方法,都會被構造函數的實例繼承。

也就是說,對于那些不變的屬性和方法,我們可以直接將其添加在類的prototype對象上。

function Cat(name,color){

this.name = name;

this.color = color;

}

Cat.prototype.type = "英短";

Cat.prototype.eat = ( () => {

alert("fish!")

} )

//生成實例

var cat1 = new Cat('Tom', 'gray');

var cat2 = new Cat('Kobe', 'purple');

console.log(cat1.type); //英短

cat2.eat(); //fish!

這時所有實例的type屬性和eat()方法,其實都是同一個內存地址,指向prototype對象,因此就提高了運行效率。

但是這樣做也有弊端,因為實例化的對象的原型都是指向同一內存地址,改動其中一個對象的屬性可能會影響到其他的對象

es6中的類和封裝

es6聲明一個類

①構造器:構造器內創建自有屬性

②方法:聲明類實例具有的方法

class Cat {

//等價于Cat構造器

constructor(name) {

this.name = name;

}

//更加簡單的聲明類的內部函數

//等價于 Cat.prototype.eat

eat() {

console.log("fish!");

}

}

//生成實例

var cat1 = new Cat("tom");

cat1.eat(); //fish!

console.log(cat1 instanceof Cat); //true

console.log(cat1 instanceof Object); //true

console.log(typeof Cat); //function

console.log(typeof Cat.prototype.eat); //function

從上面class聲明的Cat為例:Cat類是一個具有構造函數行為的函數,其中內部方法eat實際上就是Cat.prototype.eat()

所以說es6的class封裝類,本質上是es5實現方式的語法糖

最主要的區別在于,class類的屬性是不可重新賦值和不可枚舉的,Cat.prototype就是一個只讀屬性

class和自定義類型的區別

(1)class的聲明不會提升,與let類似

(2)class的聲明自動運行于嚴格模式之下

(3)class聲明的方法不可枚舉

(4)class的內部方法沒有 constructor 屬性,無法new

(5)調用class的構造函數必須new

(6)class內部方法不能同名

class類的使用

class作為js中的一級公民,可以被當作值來直接使用

//1.類名作為參數傳入函數

function createObj (ClassName) {

return new ClassName()

}

//2.立即執行,實現單例模式

let cat1 = new class{

constructor (name) {

this.name = name

}

eat() {

console.log("fish!")

}

}("tom”)

cat1.eat() //fish!

繼承

繼承就是子類可以使用父類的所有功能,并且對這些功能進行擴展。繼承的過程,就是從一般到特殊的過程。

1.類式繼承

所謂的類式繼承就是使用的原型的方式,將方法添加在父類的原型上,然后子類的原型是父類的一個實例化對象。

//聲明父類

var SuperClass = function(){

let id = 1;

this.name = ['java'];

this.superValue = function() {

console.log('this is superValue!')

}

}

//為父類添加共有方法

SuperClass.prototype.getSuperValue = function () {

return this.superValue();

};

//聲明子類

var SubClass = function() {

this.subValue = (() => {

console.log('this is subValue!')

})

}

//繼承父類

SubClass.prototype = new SuperClass();

//為子類添加共有方法

SubClass.prototype.getSubValue = function() {

return this.subValue()

}

//生成實例

var sub1 = new SubClass();

var sub2 = new SubClass();

sub1.getSuperValue(); //this is superValue!

sub1.getSubValue(); //this is subValue!

console.log(sub1.id); //undefined

console.log(sub1.name); //["java"]

sub1.name.push("php");

console.log(sub1.name); //["java", "php"]

console.log(sub2.name); //["java", "php"]

其中最核心的是SubClass.prototype = new SuperClass();

類的原型對象prototype對象的作用就是為類的原型添加共有的方法的,但是類不能直接訪問這些方法,只有將類實例化之后,新創建的對象復制了父類構造函數的屬性和方法,并將原型 proto 指向了父類的原型對象。這樣子類就可以訪問父類的屬性和方法,同時,父類中定義的屬性和方法不會被子類繼承。

but使用類繼承的方法,如果父類的構造函數中有引用數據類型,就會在子類中被所有實例共用,因此一個子類的實例如果更改了這個引用數據類型,就會影響到其他子類的實例。

構造函數繼承

為了克服類繼承的缺點,才有了構造函數繼承,構造函數繼承的核心思想就是SuperClass.call(this, id),直接改變this的指向,使通過this創建的屬性和方法在子類中復制一份,因為是單獨復制的,所以各個實例化的子類互不影響。but會造成內存浪費的問題

//構造函數繼承

//聲明父類

var SuperClass = function(id){

var name = 'java'

this.languages = ['java', 'php', 'ruby'];

this.id = id

}

//聲明子類

var SubClass = function(id){

SuperClass.call(this, id)

}

//生成實例

var sub1 = new SubClass(1);

var sub2 = new SubClass(2);

console.log(sub2.id); // 2

console.log(sub1.name); //undefined

sub1.languages.push("python");

console.log(sub1.languages); // ['java', 'php', 'ruby', 'python']

console.log(sub2.languages); // ['java', 'php', 'ruby']

組合式繼承

組合式繼承是汲取了兩者的優點,既避免了內存浪費,又使得每個實例化的子類互不影響。

//組合式繼承

//聲明父類

var SuperClass = function(name){

this.languages = ['java', 'php', 'ruby'];

this.name = name;

}

//聲明父類原型方法

SuperClass.prototype.showLangs = function () {

console.log(this.languages);

}

//聲明子類

var SubClass = function(name){

SuperClass.call(this, name)

}

//子類繼承父類(鏈式繼承)

SubClass.prototype = new SuperClass();

//生成實例

var sub1 = new SubClass('python');

var sub2 = new SubClass('go');

sub2.showLangs(); //['java', 'php', 'ruby']

sub1.languages.push(sub1.name);

console.log(sub1.languages);//["java", "php", "ruby", "python"]

console.log(sub2.languages);//['java', 'php', 'ruby']

but警告:組合式繼承方法固然好,但是會導致一個問題,父類的構造函數會被創建兩次(call()的時候一遍,new的時候又一遍)

寄生組合繼承

組合式繼承的缺點的關鍵是 父類的構造函數在類繼承和構造函數繼承的組合形式被創建了兩邊,但是在類繼承中我們并不需要創建父類的構造函數,我們只要子類繼承父類的原型即可。

所以我們先給父類的原型創建一個副本,然后修改子類的 constructor 屬性,最后在設置子類的原型就可以了

//原型式繼承

//原型式繼承其實就是類式繼承的封裝,實現的功能返回一個實例,該實例的原型繼承了傳入的o對象

function inheritObject(o) {

//聲明一個過渡函數

function F() {}

//過渡對象的原型鏈繼承父對象

F.prototype = o;

//返回一個過渡對象的實例,該實例的原型繼承了父對象

return new F();

}

//寄生式繼承

//寄生式繼承就是對原型繼承的第二次封裝,使得子類的原型等于父類的原型。并且在第二次封裝的過程中對繼承的對象進行了擴展

function inheritPrototype(subClass, superClass){

//復制一份父類的原型保存在變量中,使得p的原型等于父類的原型

var p = inheritObject(superClass.prototype);

//修正因為重寫子類原型導致子類constructor屬性被修改

p.constructor = subClass;

//設置子類的原型

subClass.prototype = p;

}

//定義父類

var SuperClass = function(name) {

this.name = name;

this.languages = ["java", "php", "python"]

}

//定義父類原型方法

SuperClass.prototype.showLangs = function() {

console.log(this.languages);

}

//定義子類

var SubClass = function(name) {

SuperClass.call(this,name)

}

inheritPrototype(SubClass, SuperClass);

var sub1 = new SubClass('go');

es6中的繼承

class SuperClass {

constructor(name) {

this.name = name

this.languages = ['java', 'php', 'go'];

}

showLangs() {

console.log(this.languages);

}

}

class SubClass extends SuperClass {

constructor(name) {

super(name)

}

//重寫父類中的方法

showLangs() {

this.languages.push(this.name)

console.log(this.languages);

}

}

//生成實例

var sub = new SubClass('韓二虎');

console.log(sub.name); //韓二虎

sub.showLangs(); //["java", "php", "go", "韓二虎"]

多態

多態實際上是不同對象作用與同一操作產生不同的效果。多態的思想實際上是把 “想做什么” 和 “誰去做” 分開。

多態的好處在于,你不必再向對象詢問“你是什么類型”后根據得到的答案再去調用對象的某個行為。你盡管去調用這個行為就是了,其他的一切可以由多態來負責。規范來說,多態最根本的作用就是通過吧過程化的條件語句轉化為對象的多態性,從而消除這些條件分支語句。

由于JavaScript中提到的關于多態的詳細介紹并不多,這里簡單的通過一個例子來介紹就好

//非多態

var hobby = function(animal){

if(animal == 'cat'){

cat.eat()

}else if(animal == 'dog'){

dog.eat()

}

}

var cat = {

eat: function() {

alert("fish!")

}

}

var dog = {

eat: function() {

alert("meat!")

}

}

console.log(123);

hobby('cat'); //fish!

hobby('dog'); //meat!

從上面的例子能看到,雖然 hobby 函數目前保持了一定的彈性,但這種彈性很脆弱的,一旦需要替換或者增加成其他的animal,必須改動hobby函數,繼續往里面堆砌條件分支語句。我們把程序中相同的部分抽象出來,那就是吃某個東西。然后再重新編程。

//多態

var hobby = function(animal){

if(animal.eat instanceof Function){

animal.eat();

}

}

var cat = {

eat: function() {

alert("fish!")

}

}

var dog = {

eat: function() {

alert("meat!")

}

}

現在來看這段代碼中的多態性。當我們向兩種 animal 發出 eat 的消息時,會分別調用他們的 eat 方法,就會產生不同的執行結果。對象的多態性提示我們,“做什么” 和 “怎么去做”是可以分開的,這樣代碼的彈性就增強了很多。即使以后增加了其他的animal,hobby函數仍舊不會做任何改變。

//多態

var hobby = function(animal){

if(animal.eat instanceof Function){

animal.eat();

}

}

var cat = {

eat: function() {

alert("fish!")

}

}

var dog = {

eat: function() {

alert("meat!")

}

}

var aoteman = {

eat: function(){

alert("lil-monster!")

}

}

hobby(cat); //fish!

hobby(dog); //meat!

hobby(aoteman); //lil-monster!

快樂面向對象😁

總結

以上是生活随笔為你收集整理的python封装继承多态_浅谈JavaScript的面向对象和它的封装、继承、多态的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 喷潮在线 | 亚洲激情综合 | 欧美一级日韩 | 亚洲国产视频一区 | 国产传媒av | 在线免费观看高清视频 | 国产美女白浆 | 久久久久久亚洲精品中文字幕 | 黄色小视频在线 | 日本在线看 | 国产欧美激情视频 | 377人体粉嫩噜噜噜 www.av黄色 | 精品国自产拍在线观看 | 热热av| 亚洲六月丁香色婷婷综合久久 | 综合免费视频 | 亚洲三级黄色片 | 久久久网站 | 超碰毛片 | 国产精品视频1区 | 国模在线观看 | 国产激情四射 | 欧美日韩影院 | 欧美14sex性hd摘花 | 国产免费麻豆 | 日韩毛片av | 蜜臀视频网站 | 中文字幕一区电影 | 涩涩视频免费在线观看 | 日韩免费高清视频 | 亚洲色图久久 | 快射视频网 | 制服丝袜av电影 | 亚洲一区二区偷拍 | 999一区二区三区 | 色婷婷亚洲一区二区三区 | 都市激情一区 | 91插插插影库永久免费 | 国产中文字幕免费 | av白浆| 国产无码精品在线观看 | 天天射天天 | 性久久久久久久久久久 | 中文字幕欧美在线 | www.久久伊人 | 国产一区二区视频在线 | 久久久久久久久久久丰满 | 91中文字幕在线观看 | 黄视频在线 | 欧美成人一区二区三区四区 | 欧美视频在线观看一区 | 亚洲综合av网 | 在厨房拨开内裤进入毛片 | av一二区 | 97香蕉久久夜色精品国产 | 免费看女人裸体 | 美女被男人桶出白浆喷水 | 日本韩国欧美一区二区三区 | 中文字幕一区二区三区精华液 | 深夜福利国产精品 | 亚洲一线av | 中文字幕成人网 | 探花视频在线免费观看 | 国产精品黄色大片 | 91无限观看| 蜜桃av一区二区三区 | 国产丝袜一区二区三区 | 中文字幕高清一区 | 奇米视频在线观看 | 男人天堂影院 | 偷拍一区二区 | 久久高清国产 | 日韩久久高清 | 久久综合第一页 | 久久精品精品 | 91精品国产高清 | 中文字幕一区二区人妻电影丶 | 婷婷深爱五月 | 久久精品视频一区二区 | 日韩欧美一区二区一幕 | 精品成人中文无码专区 | 女同av网站 | 日本久久中文字幕 | 国产精品无码一区二区三 | 五月天男人天堂 | 中文字幕+乱码+中文字幕明步 | 色婷婷狠狠爱 | 中文永久免费观看 | 丁香av| 直接看av的网站 | 福利资源在线 | 怡春院国产 | 人人九九精 | 欧美性生活一区二区 | 欧美成人一区二区视频 | 99免费视频 | 中文字幕无码毛片免费看 | 免费观看黄网站 | 日韩欧美不卡 |