面向对象简称是OOP,是目前主流的编程思想,JavaScript本身也是面向对象的编程语言,对于动态网页行为的编程,只要稍微对它有了解就可以的。对象这个词在是从英文“object”中翻译过来的,在之前的编程过程中,我们过多的考虑的是计算机硬件的工作方式,导致编程的难度增加,经过不断的发展和改良,主流的程序语言在想人类的自然语言转变,不过编程的思想还是没有重大性的突破。
对象就是人对各种具体物体抽象之后的概念,人们每天都在跟各种各样的对象打交道,比如说一本书就是一个对象。在面向对象的编程过程中,对象有很多的特性,比如说高度、宽度、颜色等等,这些都是对象的属性,而且对象还有更多的功能,比如一部手机,可以听歌,看视频,打电话,这些可以理解成有个对象的方法,这些方法可以看成是函数,并且对象不是孤立的,它还具有对象的继承性。在编程的过程中,我们可以把所有的问题看做是对象,以人的思维解决问题。对象实际上就是一组数据的集合,并且都已经被命名,这些数据的根据就是对象的属性,可以被访问。如果想访问一个外部的对象我们就必须先引进它,好比你想用国外的东西一样,只有你从国外把它带回来你才能使用。那么下面我们就看看如何创建一个对象吧:在我们JavaScript内部有很多是内置对象,我们也可以直接创建一个新的对象,创建对象的方法就是使用new运算符和构造函数,eg:var new_name=new 构造函数;预先定义的构造函数直接直接决定所创建对象的类型,如果想创建一个空的对象,可以使用object()构造函数。还有就是定义对象的属性,其实定义对象的属性很简单,直接在对象后面用点运算符号声明属性的名称,并可直接赋值。创建对象所用的构造函数是预定义的,如Object()可以用于创建一个空对象,而创建数组对象我们可以使用Array()构造函数。这些都是些内置的构造函数,当然我们也可以自定义,就是自定义构造函数,比如你想构造有个食物的对象,就是构造food()的对象,通过向这个构造函数传递参数以初始化对象实例。不过构造函数只能初始化对象实例而不能返回对象实例,需要使用new运算符才能创建食物的对象实例。
1)对象:对象是人们要进行研究的任何事物,它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。对象具有状态,一个对象用数据值来描述它的状态。对象还有操作,用于改变对象的状态,对象及其操作就是对象的行为。对象实现了数据和操作的结合,使数据和操作封装于对象的统一体中。
2)类:具有相同特性(数据元素)和行为(功能)的对象的抽象就是类。因此,对象的抽象是类,类的具体化就是对象,也可以说类的实例是对象,类实际上就是一种数据类型。类具有属性,它是对象的状态的抽象,用数据结构来描述类的属性。类具有操作,它是对象的行为的抽象,用操作名和实现该操作的方法来描述。
类与对象的关系就如模具和铸件的关系,类的实力化的结果就是对象,而对对象的抽象就是类,类描述了一组有相同特性(属性)和相同行为的对象。
第一种方法:
class Call:
def setName(self, name):
self.name = name
def kick(self):
print("我的名字是{}".format(self.name))
call = Call()
call.setName("DaShuaige")
print(call.kick())
这种方法需要先声明一个对象,然后通过一个函数将参数传入对象中。
第二种方法:
class Ball:
def __init__(self, name):
self.name = name
def kick(self):
print("我叫{}".format(self.name))
ball = Ball("DaHaoren")
print(ball.kick())
这种方法在声明一个对象的时候考研将参数直接通过调用类导入对象当中。
1,类是一个抽象的概念,它不存在于现实中的时间/空间里,类只是为所有的对象定义了抽象的属性与行为。就好像“Person(人)”这个类,它虽然可以包含很多个体,但它本身不存在于现实世界上。
2,对象是类的一个具体。它是一个实实在在存在的东西。
3,类是一个静态的概念,类本身不携带任何数据。当没有为类创建任何对象时,类本身不存在于内存空间中。
4,对象是一个动态的概念。每一个对象都存在着有别于其它对象的属于自己的独特的属性和行为。对象的属性可以随着它自己的行为而发生改变。
为了保护敏感/隐私属性数据,让外界访问当前对象中的属性数据时,可以按照我们指定的条件进行访问,否则不允许访问,提高属性数据的安全性。
class Person:
def __init__(self, name, age):
self.__name = name
self.__age = age
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_age(self, age):
if 18 <= age <= 40:
self.__age = age
else:
print("输入年龄不合法")
def get_age(self):
return self.__age
# 创建用户对象
p = Person("tom", 18)
print(p.get_name(), p.get_age())
# 修改对象的属性数据
p.set_name("jerry")
p.set_age(1000)
print(p.get_name(), p.get_age())
class User:
"""用户类型"""
def __init__(self, username, password):
self.__username = username
self.__password = password
def set_username(self, username):
self.__username = username
def get_username(self):
return self.__username
def set_password(self, password):
self.__password = password
def get_password(self):
return self.__password
误区:私有属性,完全不能直接访问
我们定义了私有属性,就是两个下划线开头的属性
理论上外界不能直接访问,而是要通过我们提供的set/get方法间接访问
功能开发过程中,代码和功能都可能会存在一些问题
如果发现问题~一定要及时沟通,而不是私自修改。
class Person:
def __init__(self, name):
self.__name = name
p = Person("tom")
#私有属性破坏性访问方式:我们自己要知道,但是严禁使用
p._Person__name = "jerry"
print(p._Person__name)
误区:关于对象属性的扩展
class Goods:
def __init__(self, name, price):
self.__name = name
self.__price = price
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_price(self, price):
self.__price = price
def get_price(self):
return self.__price
car = Goods("奥拓", 18000)
print("car的价格:", car.get_price())
# 如果通过 对象的引用变量.属性 直接赋值,该属性又不是类型中定义的属性
# 这个属性就是 单独属于这个对象 的扩展属性。
car.__price = 20000
print("car的价格", car.__price, "---", car.get_price())
# 扩展属性,属于对象car
car.__color = "红色"
print(car.__color)
# car2 = Goods("奥迪", 300000)
# print(car2.__color)
"""
但是,这样的扩展方式,破坏了原有的封装语法,让代码的可读性出现了严重的下降
解决方案:在类型中,定义好~该对象可以出现的属性,其他任何扩展属性就不能添加了。
"""
class Pet:
"""宠物类型:限制该类型只能出现哪些属性"""
# 限制该类型的对象,只能拥有下面列表中出现的属性
__slots__ = ['__name', '__age', '__gender', 'color']
def __init__(self, name, age, gender):
self.__name = name
self.__age = age
self.__gender = gender
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_age(self, age):
self.__age = age
def get_age(self):
return self.__age
def set_gender(self, gender):
self.__gender = gender
def get_gender(self):
return self.__gender
p = Pet("tomcat", 18, "公")
print(p.get_name(), p.get_age(), p.get_gender())
# 扩展属性
p.color = "灰色"
print(p.get_name(), p.get_age(), p.get_gender(), p.color)
p.email = "[email protected]"
print(p.email)
概念:继承是指在已存在的类的基础上扩展产生新的类。已存在的类称为基类(或父类、超类),新产生的类称为子类(或派生类)。
意义:继承是面向对象程序设计的三大特征(封装、继承和多态)之一,不具有继承功能的语言不能称之为面向对象程序设计语言(如VB),继承具有如下特点: 继承划分了类的层次性,父类代表的是更一般、更泛化的类,而子类则是更为具体、更为细化; 继承是实现代码重用、扩展软件功能的重要手段,子类中与父类完全相同的属性和方法不必重写,只需写出新增或改写的内容,这就是说子类可以复用父类的内容,不必一切从零开始。
继承基本语法
体现的是,某个小类型,属于某个大类型的
如:男人 是 人 的一种类型
生活中:约定
代码中:约定 Man类型就是Person类型 非强制
代码中:强制约束:通过继承关系,体现某个类型属于另一个类型
关于继承:
python中的所有类型,都是直接或者间接继承自object类型的
object:对象 万物皆对象
python3中类型声明语法:
class 类型名称: # 隐式继承object类型
pass
class 类型名称(object): # 显式继承object类型
pass
python2中类型的声明语法:
class 类型名称: # 经典类
pass
class 类型名称(object): # 新式类
pass
继承的语法:
class 类型名称(要继承的类型):
pass
继承的特性:
代码中出现了继承,类型就出现了新的名称:
被继承的类型:父类
当前类型:子类
体现的是:子类继承父类
子类中就可以继承父类中的属性和方法【公共】
子类中可以直接使用父类的属性和方法
class Person:
"""人的类型"""
def __init__(self, name):
self.name = name
class Man(Person):
"""男人"""
pass
tianqi = Man("jerry")
mingxin = Man("jerry")
da_sheng = tianqi
print(type(tianqi))
# 运算符:类型判断运算符 isinstance
print(isinstance(tianqi, Man))
print(isinstance(tianqi, Person))
# 运算符:对象判断运算符 is
print(tianqi is Man)
print(tianqi is Person)
print(tianqi is mingxin)
print(tianqi is da_sheng)
print(tianqi == da_sheng)
'''
子类对象使用父类数据
'''
class Person:
def __init__(self, name, age, gender):
self.name = name
self._age = age
self.__gender = gender
def say(self):
print(self.name, "滚去学习")
def _play(self):
print(self.name, "滚去玩")
def __sleep(self):
print(self.name, "嗨什么嗨,滚去睡觉")
class Child(Person):
pass
c = Child("jerry", 18, "男")
print(c.name)# 对象访问父类中的属性
print(c._age)# 对象访问父类中的属性
# print(c.__gender)# 对象访问父类中的私有属性:ERROR
c.say()# 对象访问父类中的方法
c._play()# 对象访问父类中的方法
# c.__sleep()# 对象访问父类中的私有方法:ERROR
'''
子类类型使用父类数据
1. 子类中访问父类的方法
super().方法名称()
注意:访问属性时~可能会出错。扩展~为什么会出错?
2. 子类的__init__()方法
如果子类中不写__init__()方法,直接使用父类的__init__()方法初始化数据
怎么访问:如果子类中写了自己的__init__()方法,一定要调用执行父类的__init__()方法
什么时候访问:什么时候子类写自己的__init__()方法,子类中出现独立属性时!
为什么要访问:?
3. 子类中可以重新定义从父类中继承的方法【方法名称和方法参数一致】:方法重写
方法重写:子类中重写父类中已经存在的方法
在执行过程中~如果子类中重写了方法,执行子类的方法,如果没有重写则执行父类中的方法【运行过程中的多种状态切换:运行时多态】
在继承关系中,python中有两种事物的存在:
数据类型-> 所有的类型,都是直接继承自type类型的
对象-> 所有对象都是直接或者间接继承自object对象的
python中所有的数据,都是直接或者间接继承自type类型的。
重点:区分类型和对象的区别
'''
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def say(self):
print(self.name, "滚去学习")
def play(self):
print(self.name, "出门打麻将")
def sleep(self):
print(self.name, "嗨什么嗨,滚去睡觉")
class Child(Person):
def __init__(self, name, age, gender, email, phone):
super().__init__(name, age, gender)
self.email = email
self.phone = phone
def speek(self):
"""子类的方法"""
# 访问父类的属性和方法
# print("子类speek中访问父类的属性:", super().name)
super().say()
print("子类的speek方法执行中......")
def play(self):
print(self.name, "搭积木.........")
c = Child("tom", 18, "男", "[email protected]", "15682808270")
c.speek()
print(c.email)
c.play()
p = Person("jerry", 20, "女")
p.play()
# print(p.email)
"""
既然出现了继承,python中的所有对象都是直接或者间接继承object
1.我们都继承了什么?
构造方法
__new__ 创建对象的方法 一般不使用~直接通过父类创建对象即可。
__init__ 初始化数据的方法 一般会重写该方法,用来初始化对象数据
__slots__ 封装时,限制属性的
__str__ 对象字符打印方式;默认情况打印内存中16进制表示的位置
__repr__ 交互模式中,字符打印方式
__hash__ 获取兑现的hash数据,用于判断的依据
__ne__ 不等于:not equals;两个对象使用!=判断的
__ge__ 大于等于:grant or equals 判断 >=
__gt__ 大于: grant than判断 >
__le__ 小于等于:less or equals 判断 <=
__lt__ 小于 less than 判断 <
__eq__ 判断等于 equals 判断 ==
__dict__ 将对象转换成字典
__doc__ 说明文档
__class__ 类型,类似于type
__format__
__getattribute__
__delattr__
__sizeof__
__reduce__
__reduce_ex__
__dir__
____init_subclass__
__module__
__setattr__ 给属性设置数据-一般不重写
2. 这些继承的东西有什么作用?
"""
class Person:
"""人的类型"""
def __init__(self, name, age):
"""
人的类型初始化函数
:param name: 初始化的姓名
:param age: 初始化的年龄
"""
self.name = name
self.age = age
def __str__(self):
return f"人:[name:{self.name}, age:{self.age}]"
def __hash__(self):
return self.name.__hash__()
def __eq__(self, other):
# 判断两个对象~是否相等,按照业务逻辑 姓名和年龄一样,表示是同一个人
if self.name == other.name and self.age == other.age:
return True
return False
def __gt__(self, other):
# 判断两人的大小:业务判断~按照年龄判断
if self.age > other.age:
return True
return False
def __ge__(self, other):
if self.age >= other.age:
return True
return False
def sleep(self, area):
"""
睡觉了
:param area 这是一个方法的参数说明
"""
# 创建对象
p1 = Person("tom", 18)
# 打印对象 0x000001E265E7ADA0~ 内存中的地址 16进制字符表示方式
print(p1) # <__main__.Person object at 0x000001E265E7ADA0>
p2 = Person("tom", 18)
print(p1 == p2)
print(p1 > p2)
print(p1 >= p2)
print(p1.__dict__)
print(p1.__doc__)
print(p1.sleep.__doc__)
"""
python中的多继承
体现的是什么样的编程思想:一个对象在不同场景中,可能扮演不同的角色【设计时多态】
"""
class Son:
def xiao_shun(self):
print("百善孝为先")
class Student:
def xue_xi(self):
print("好好学习,天天向上")
class Friend:
def play(self):
print("吃喝玩乐.....")
class Person(Son, Student, Friend):
"""人的类型:继承儿子、学生、朋友"""
pass
p = Person()
# 家庭环境
if isinstance(p, Son):
p.xiao_shun()
# 学习环境中
if isinstance(p, Student):
p.xue_xi()
# 朋友
if isinstance(p, Friend):
p.play()
def xue_tang(person):
# 作为一个学员,在教室要好好学习
if isinstance(person, Student):
# person.play()
person.xue_xi()
xue_tang(p)
python中的多继承
体现的是什么样的编程思想:一个对象在不同场景中,可能扮演不同的角色【设计时多态】
问题:如果不同的父类出现了相同名称的属性或者方法
子类会继承谁的属性或者方法?
python3中都是新式类:广度优先,从父类中查询对应的方法,查询到第一个满足的方法之后就直接返回
object
|
A(object)
|
A_1(A) --> A_2(A)
|
Test(A_1, A_2)
python2中的经典类:深度优先
A
|
A --> A_2(A)
|
A_1(A)
|
Test(A_1, A_2)
class A:
def test(self):
print("aaaaaaaaaaaaaaaaa")
class A_1(A):
def test(self):
print("1111111111111111111")
class A_2(A):
def test(self):
print("2222222222222222222")
class Test(A_1, A_2):
pass
t = Test()
t.test() # 1111111111111111111
# [, , , , ]
print(Test.mro())
方法重写实现运行时多态,对象在执行具体的方法时,会直接执行父类中继承的对应的方法,如果该方法在子类中重写了,就会执行子类中重写过的方法,实现的是一种运行过程中的多态处理
# 定义父类
class Person(object):
def __init__(self, name):
self.__name = name
def playing(self):
print(self.__name + "正在游戏中...")
# 定义子类,继承自Person
class Man(Person):
def __init__(self, name):
Person.__init__(self, name)
# 定义子类,继承自Person
class Women(Person):
def __init__(self, name):
Person.__init__(self, name)
def playing(self):
print(self.__name + "正在游戏封装找茬中...")
# 创建对象
man = Man("tom")
women = Women("jerry")
man.playing() # 子类中没有重写,直接执行从父类继承的playing()函数
women.playing() #子类中重写了,直接执行子类中的playing()函数
python中的多继承
一个对象在不同场景中,可能扮演不同的角色
class Son:
def xiao_shun(self):
print("百善孝为先")
class Student:
def xue_xi(self):
print("好好学习,天天向上")
class Friend:
def play(self):
print("吃喝玩乐.....")
class Person(Son, Student, Friend):
"""人的类型:继承儿子、学生、朋友"""
pass
p = Person()
# 家庭环境
if isinstance(p, Son):
p.xiao_shun()
# 学习环境中
if isinstance(p, Student):
p.xue_xi()
# 朋友
if isinstance(p, Friend):
p.play()
def xue_tang(person):
# 作为一个学员,在教室要好好学习
if isinstance(person, Student):
# person.play()
person.xue_xi()
xue_tang(p)
多态~和封装以及继承不同的是,没有固定的语法,没有固定的思路,只有操作的方式。从项目中体现。