把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派。
简单的说,类是对象的蓝图和模板,而对象是类的实例。这个解释虽然有点像用概念在解释概念,但是从这句话我们至少可以看出,类是抽象的概念,而对象是具体的东西。在面向对象编程的世界中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一个叫做“类”的东西。

定义类
在Python中可以使用class关键字定义类,然后在类中通过之前学习过的函数来定义方法,这样就可以将对象的动态特征描述出来,代码如下所示。
说明: 写在类中的函数,我们通常称之为(对象的)方法,这些方法就是对象可以接收的消息。

class Student(object):# __init__是一个特殊方法用于在创建对象时进行初始化操作# 通过这个方法我们可以为学生对象绑定name和age两个属性def __init__(self, name, age):self.name = nameself.age = agedef study(self, course_name):print('%s正在学习%s.' % (self.name, course_name))# PEP 8要求标识符的名字用全小写多个单词用下划线连接# 但是部分程序员和公司更倾向于使用驼峰命名法(驼峰标识)def watch_movie(self):if self.age < 18:print('%s只能观看《熊出没》.' % self.name)else:print('%s正在观看岛国爱情大电影.' % self.name)

创建和使用对象
当我们定义好一个类之后,可以通过下面的方式来创建对象并给对象发消息。

def main():# 创建学生对象并指定姓名和年龄stu1 = Student('骆昊', 38)# 给对象发study消息stu1.study('Python程序设计')# 给对象发watch_av消息stu1.watch_movie()stu2 = Student('王大锤', 15)stu2.study('思想品德')stu2.watch_movie()if __name__ == '__main__':main()

完整代码:

class Student(object):# __init__是一个特殊方法用于在创建对象时进行初始化操作# 通过这个方法我们可以为学生对象绑定name和age两个属性def __init__(self, name, age):self.name = nameself.age = agedef study(self, course_name):print('%s正在学习%s.' % (self.name, course_name))# PEP 8要求标识符的名字用全小写多个单词用下划线连接# 但是部分程序员和公司更倾向于使用驼峰命名法(驼峰标识)def watch_movie(self):if self.age < 18:print('%s只能观看《熊出没》.' % self.name)else:print('%s正在观看岛国爱情大电影.' % self.name)def main():# 创建学生对象并指定姓名和年龄stu1 = Student('骆昊', 38)# 给对象发study消息stu1.study('Python程序设计')# 给对象发watch_av消息stu1.watch_movie()stu2 = Student('王大锤', 15)stu2.study('思想品德')stu2.watch_movie()if __name__ == '__main__':main()


总结:一个对象(学生),两个属性(姓名和年龄),两个行为(也叫方法)(学习和看电影),其中两个行为用函数def定义,两个属性用特殊方法__int__为对象进行绑定。最后要注意,用class定义对象的时候,首字母大写。

私有属性(方法)并不私密
但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来“妨碍”对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是“We are all consenting adults here”。因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。

注意:定义了私有属性foo和私有方法bar,但是仍然可以通过特殊方法进行访问。

class Test:def __init__(self, foo):self.__foo = foodef __bar(self):print(self.__foo)print('__bar')def main():test = Test('hello')test._Test__bar()print(test._Test__foo)if __name__ == "__main__":main()

面向对象的支柱-封装
面向对象有三大支柱:封装、继承和多态。对封装的理解是“隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口”。我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。

练习
练习1:定义一个类描述数字时钟

from time import sleepclass Clock(object):"""数字时钟"""def __init__(self, hour=0, minute=0, second=0):"""初始化方法:param hour: 时:param minute: 分:param second: 秒"""self._hour = hourself._minute = minuteself._second = seconddef run(self):"""走字"""self._second += 1if self._second == 60:self._second = 0self._minute += 1if self._minute == 60:self._minute = 0self._hour += 1if self._hour == 24:self._hour = 0def show(self):"""显示时间"""return '%02d:%02d:%02d' % \(self._hour, self._minute, self._second)def main():clock = Clock(23, 59, 58)while True:print(clock.show())sleep(1)clock.run()if __name__ == '__main__':main()


练习2:定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法。

from math import sqrtclass Point(object):def __init__(self, x=0, y=0):"""初始化方法:param x: 横坐标:param y: 纵坐标"""self.x = xself.y = ydef move_to(self, x, y):"""移动到指定位置:param x: 新的横坐标"param y: 新的纵坐标"""self.x = xself.y = ydef move_by(self, dx, dy):"""移动指定的增量:param dx: 横坐标的增量"param dy: 纵坐标的增量"""self.x += dxself.y += dydef distance_to(self, other):"""计算与另一个点的距离:param other: 另一个点"""dx = self.x - other.xdy = self.y - other.yreturn sqrt(dx ** 2 + dy ** 2)def __str__(self):return '(%s, %s)' % (str(self.x), str(self.y))def main():p1 = Point(3, 5)p2 = Point()print(p1)print(p2)p2.move_by(-1, 2)print(p2)print(p1.distance_to(p2))if __name__ == '__main__':main()


@property装饰器
之前我们讨论过Python中属性和方法访问权限的问题,虽然我们不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效。我们之前的建议是将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作。如果要做到这点,就可以考虑使用@property包装器来包装getter和setter方法,使得对属性的访问既安全又方便,代码如下所示。

class Person(object):def __init__(self, name, age):self._name = nameself._age = age# 访问器 - getter方法@propertydef name(self):return self._name# 访问器 - getter方法@propertydef age(self):return self._age# 修改器 - setter方法@age.setterdef age(self, age):self._age = agedef play(self):if self._age <= 16:print('%s正在玩飞行棋.' % self._name)else:print('%s正在玩斗地主.' % self._name)def main():person = Person('王大锤', 12)person.play()person.age = 22person.play()# person.name = '白元芳'  # AttributeError: can't set attributeif __name__ == '__main__':main()


__slots__魔法
Python是一门动态语言。通常,动态语言允许我们在程序运行时给对象绑定新的属性或方法,当然也可以对已经绑定的属性和方法进行解绑定。但是如果我们需要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义__slots__变量来进行限定。需要注意的是__slots__的限定只对当前类的对象生效,对子类并不起任何作用。

class Person(object):# 限定Person对象只能绑定_name, _age和_gender属性__slots__ = ('_name', '_age', '_gender')def __init__(self, name, age):self._name = nameself._age = age@propertydef name(self):return self._name@propertydef age(self):return self._age@age.setterdef age(self, age):self._age = agedef play(self):if self._age <= 16:print('%s正在玩飞行棋.' % self._name)else:print('%s正在玩斗地主.' % self._name)def main():person = Person('王大锤', 22)person.play()person._gender = '男'# AttributeError: 'Person' object has no attribute '_is_gay'# person._is_gay = Trueif __name__ == '__main__':main()


静态方法和类方法
我们在类中定义的方法都是对象方法,也就是说这些方法都是发送给对象的消息。实际上,我们写在类中的方法并不需要都是对象方法,例如我们定义一个“三角形”类,通过传入三条边长来构造三角形,并提供计算周长和面积的方法,但是传入的三条边长未必能构造出三角形对象,因此我们可以先写一个方法来验证三条边长是否可以构成三角形,这个方法很显然就不是对象方法,因为在调用这个方法时三角形对象尚未创建出来(因为都不知道三条边能不能构成三角形),所以这个方法是属于三角形类而并不属于三角形对象的。我们可以使用静态方法来解决这类问题,代码如下所示。

from math import sqrtclass Triangle(object):def __init__(self, a, b, c):self._a = aself._b = bself._c = c@staticmethoddef is_valid(a, b, c):return a + b > c and b + c > a and a + c > bdef perimeter(self):return self._a + self._b + self._cdef area(self):half = self.perimeter() / 2return sqrt(half * (half - self._a) *(half - self._b) * (half - self._c))def main():a, b, c = 3, 4, 5# 静态方法和类方法都是通过给类发消息来调用的if Triangle.is_valid(a, b, c):t = Triangle(a, b, c)print(t.perimeter())# 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数# print(Triangle.perimeter(t))print(t.area())# print(Triangle.area(t))else:print('无法构成三角形.')if __name__ == '__main__':main()


和静态方法比较类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息的对象(类本身也是一个对象,有的地方也称之为类的元数据对象),通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象,代码如下所示。

from time import time, localtime, sleepclass Clock(object):"""数字时钟"""def __init__(self, hour=0, minute=0, second=0):self._hour = hourself._minute = minuteself._second = second@classmethoddef now(cls):ctime = localtime(time())return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)def run(self):"""走字"""self._second += 1if self._second == 60:self._second = 0self._minute += 1if self._minute == 60:self._minute = 0self._hour += 1if self._hour == 24:self._hour = 0def show(self):"""显示时间"""return '%02d:%02d:%02d' % \(self._hour, self._minute, self._second)def main():# 通过类方法创建对象并获取系统时间clock = Clock.now()while True:print(clock.show())sleep(1)clock.run()if __name__ == '__main__':main()


类之间的关系
简单的说,类和类之间的关系有三种:is-a、has-a和use-a关系。

  • is-a关系也叫继承或泛化,比如学生和人的关系、手机和电子产品的关系都属于继承关系。(属于,包含)
  • has-a关系通常称之为关联,比如部门和员工的关系,汽车和引擎的关系都属于关联关系;关联关系如果是整体和部分的关联,那么我们称之为聚合关系;如果整体进一步负责了部分的生命周期(整体和部分是不可分割的,同时同在也同时消亡),那么这种就是最强的关联关系,我们称之为合成关系。(荣辱与共,相互依存)
  • use-a关系通常称之为依赖,比如司机有一个驾驶的行为(方法),其中(的参数)使用到了汽车,那么司机和汽车的关系就是依赖关系。(打枪和扣动扳机)

我们可以使用一种叫做UML(统一建模语言)的东西来进行面向对象建模,其中一项重要的工作就是把类和类之间的关系用标准化的图形符号描述出来。

利用类之间的这些关系,我们可以在已有类的基础上来完成某些操作,也可以在已有类的基础上创建新的类,这些都是实现代码复用的重要手段。复用现有的代码不仅可以减少开发的工作量,也有利于代码的管理和维护,这是我们在日常工作中都会使用到的技术手段。

继承和多态
刚才我们提到了,可以在已有类的基础上创建新类,这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写。提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有的更多的能力,在实际开发中,我们经常会用子类对象去替换掉一个父类对象,这是面向对象编程中一个常见的行为,对应的原则称之为里氏替换原则。下面我们先看一个继承的例子。

class Person(object):"""人"""def __init__(self, name, age):self._name = nameself._age = age@propertydef name(self):return self._name@propertydef age(self):return self._age@age.setterdef age(self, age):self._age = agedef play(self):print('%s正在愉快的玩耍.' % self._name)def watch_av(self):if self._age >= 18:print('%s正在观看爱情动作片.' % self._name)else:print('%s只能观看《熊出没》.' % self._name)class Student(Person):"""学生"""def __init__(self, name, age, grade):#继承上面的name和agesuper().__init__(name, age)self._grade = grade@propertydef grade(self):return self._grade@grade.setterdef grade(self, grade):self._grade = gradedef study(self, course):print('%s的%s正在学习%s.' % (self._grade, self._name, course))class Teacher(Person):"""老师"""def __init__(self, name, age, title):super().__init__(name, age)self._title = title@propertydef title(self):return self._title@title.setterdef title(self, title):self._title = titledef teach(self, course):print('%s%s正在讲%s.' % (self._name, self._title, course))def main():stu = Student('王大锤', 15, '初三')stu.study('数学')stu.watch_av()t = Teacher('骆昊', 38, '砖家')t.teach('Python程序设计')t.watch_av()if __name__ == '__main__':main()


子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。

from abc import ABCMeta, abstractmethodclass Pet(object, metaclass=ABCMeta):"""宠物"""def __init__(self, nickname):self._nickname = nickname@abstractmethoddef make_voice(self):"""发出声音"""passclass Dog(Pet):"""狗"""def make_voice(self):print('%s: 汪汪汪...' % self._nickname)class Cat(Pet):"""猫"""def make_voice(self):print('%s: 喵...喵...' % self._nickname)def main():pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]for pet in pets:pet.make_voice()if __name__ == '__main__':main()


在上面的代码中,我们将Pet类处理成了一个抽象类,所谓抽象类就是不能够创建对象的类,这种类的存在就是专门为了让其他类去继承它。Python从语法层面并没有像Java或C#那样提供对抽象类的支持,但是我们可以通过abc模块的ABCMeta元类和abstractmethod包装器来达到抽象类的效果,如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)。上面的代码中,Dog和Cat两个子类分别对Pet类中的make_voice抽象方法进行了重写并给出了不同的实现版本,当我们在main函数中调用该方法时,这个方法就表现出了多态行为(同样的方法做了不同的事情)。

练习
案例1:奥特曼打小怪兽。

from abc import ABCMeta, abstractmethod
from random import randint, randrangeclass Fighter(object, metaclass=ABCMeta):"""战斗者"""# 通过__slots__魔法限定对象可以绑定的成员变量__slots__ = ('_name', '_hp')def __init__(self, name, hp):"""初始化方法:param name: 名字:param hp: 生命值"""self._name = nameself._hp = hp@propertydef name(self):return self._name@propertydef hp(self):return self._hp@hp.setterdef hp(self, hp):self._hp = hp if hp >= 0 else 0@propertydef alive(self):return self._hp > 0@abstractmethoddef attack(self, other):"""攻击:param other: 被攻击的对象"""passclass Ultraman(Fighter):"""奥特曼"""__slots__ = ('_name', '_hp', '_mp')def __init__(self, name, hp, mp):"""初始化方法:param name: 名字:param hp: 生命值:param mp: 魔法值"""super().__init__(name, hp)self._mp = mpdef attack(self, other):other.hp -= randint(15, 25)def huge_attack(self, other):"""究极必杀技(打掉对方至少50点或四分之三的血):param other: 被攻击的对象:return: 使用成功返回True否则返回False"""if self._mp >= 50:self._mp -= 50injury = other.hp * 3 // 4injury = injury if injury >= 50 else 50other.hp -= injuryreturn Trueelse:self.attack(other)return Falsedef magic_attack(self, others):"""魔法攻击:param others: 被攻击的群体:return: 使用魔法成功返回True否则返回False"""if self._mp >= 20:self._mp -= 20for temp in others:if temp.alive:temp.hp -= randint(10, 15)return Trueelse:return Falsedef resume(self):"""恢复魔法值"""incr_point = randint(1, 10)self._mp += incr_pointreturn incr_pointdef __str__(self):return '~~~%s奥特曼~~~\n' % self._name + \'生命值: %d\n' % self._hp + \'魔法值: %d\n' % self._mpclass Monster(Fighter):"""小怪兽"""__slots__ = ('_name', '_hp')def attack(self, other):other.hp -= randint(10, 20)def __str__(self):return '~~~%s小怪兽~~~\n' % self._name + \'生命值: %d\n' % self._hpdef is_any_alive(monsters):"""判断有没有小怪兽是活着的"""for monster in monsters:if monster.alive > 0:return Truereturn Falsedef select_alive_one(monsters):"""选中一只活着的小怪兽"""monsters_len = len(monsters)while True:index = randrange(monsters_len)monster = monsters[index]if monster.alive > 0:return monsterdef display_info(ultraman, monsters):"""显示奥特曼和小怪兽的信息"""print(ultraman)for monster in monsters:print(monster, end='')def main():u = Ultraman('骆昊', 1000, 120)m1 = Monster('狄仁杰', 250)m2 = Monster('白元芳', 500)m3 = Monster('王大锤', 750)ms = [m1, m2, m3]fight_round = 1while u.alive and is_any_alive(ms):print('========第%02d回合========' % fight_round)m = select_alive_one(ms)  # 选中一只小怪兽skill = randint(1, 10)   # 通过随机数选择使用哪种技能if skill <= 6:  # 60%的概率使用普通攻击print('%s使用普通攻击打了%s.' % (u.name, m.name))u.attack(m)print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))elif skill <= 9:  # 30%的概率使用魔法攻击(可能因魔法值不足而失败)if u.magic_attack(ms):print('%s使用了魔法攻击.' % u.name)else:print('%s使用魔法失败.' % u.name)else:  # 10%的概率使用究极必杀技(如果魔法值不足则使用普通攻击)if u.huge_attack(m):print('%s使用究极必杀技虐了%s.' % (u.name, m.name))else:print('%s使用普通攻击打了%s.' % (u.name, m.name))print('%s的魔法值恢复了%d点.' % (u.name, u.resume()))if m.alive > 0:  # 如果选中的小怪兽没有死就回击奥特曼print('%s回击了%s.' % (m.name, u.name))m.attack(u)display_info(u, ms)  # 每个回合结束后显示奥特曼和小怪兽的信息fight_round += 1print('\n========战斗结束!========\n')if u.alive > 0:print('%s奥特曼胜利!' % u.name)else:print('小怪兽胜利!')if __name__ == '__main__':main()




案例2:扑克游戏

import randomclass Card(object):"""一张牌"""def __init__(self, suite, face):self._suite = suiteself._face = face@propertydef face(self):return self._face@propertydef suite(self):return self._suitedef __str__(self):if self._face == 1:face_str = 'A'elif self._face == 11:face_str = 'J'elif self._face == 12:face_str = 'Q'elif self._face == 13:face_str = 'K'else:face_str = str(self._face)return '%s%s' % (self._suite, face_str)def __repr__(self):return self.__str__()class Poker(object):"""一副牌"""def __init__(self):self._cards = [Card(suite, face) for suite in '♠♥♣♦'for face in range(1, 14)]self._current = 0@propertydef cards(self):return self._cardsdef shuffle(self):"""洗牌(随机乱序)"""self._current = 0random.shuffle(self._cards)@propertydef next(self):"""发牌"""card = self._cards[self._current]self._current += 1return card@propertydef has_next(self):"""还有没有牌"""return self._current < len(self._cards)class Player(object):"""玩家"""def __init__(self, name):self._name = nameself._cards_on_hand = []@propertydef name(self):return self._name@propertydef cards_on_hand(self):return self._cards_on_handdef get(self, card):"""摸牌"""self._cards_on_hand.append(card)def arrange(self, card_key):"""玩家整理手上的牌"""self._cards_on_hand.sort(key=card_key)# 排序规则-先根据花色再根据点数排序
def get_key(card):return (card.suite, card.face)def main():p = Poker()p.shuffle()players = [Player('东邪'), Player('西毒'), Player('南帝'), Player('北丐')]for _ in range(13):for player in players:player.get(p.next)for player in players:print(player.name + ':', end=' ')player.arrange(get_key)print(player.cards_on_hand)if __name__ == '__main__':main()


案例3:工资结算系统

"""
某公司有三种类型的员工 分别是部门经理、程序员和销售员
需要设计一个工资结算系统 根据提供的员工信息来计算月薪
部门经理的月薪是每月固定15000元
程序员的月薪按本月工作时间计算 每小时150元
销售员的月薪是1200元的底薪加上销售额5%的提成
"""
from abc import ABCMeta, abstractmethodclass Employee(object, metaclass=ABCMeta):"""员工"""def __init__(self, name):"""初始化方法:param name: 姓名"""self._name = name@propertydef name(self):return self._name@abstractmethoddef get_salary(self):"""获得月薪:return: 月薪"""passclass Manager(Employee):"""部门经理"""def get_salary(self):return 15000.0class Programmer(Employee):"""程序员"""def __init__(self, name, working_hour=0):super().__init__(name)self._working_hour = working_hour@propertydef working_hour(self):return self._working_hour@working_hour.setterdef working_hour(self, working_hour):self._working_hour = working_hour if working_hour > 0 else 0def get_salary(self):return 150.0 * self._working_hourclass Salesman(Employee):"""销售员"""def __init__(self, name, sales=0):super().__init__(name)self._sales = sales@propertydef sales(self):return self._sales@sales.setterdef sales(self, sales):self._sales = sales if sales > 0 else 0def get_salary(self):return 1200.0 + self._sales * 0.05def main():emps = [Manager('刘备'), Programmer('诸葛亮'),Manager('曹操'), Salesman('荀彧'),Salesman('吕布'), Programmer('张辽'),Programmer('赵云')]for emp in emps:if isinstance(emp, Programmer):emp.working_hour = int(input('请输入%s本月工作时间: ' % emp.name))elif isinstance(emp, Salesman):emp.sales = float(input('请输入%s本月销售额: ' % emp.name))# 同样是接收get_salary这个消息但是不同的员工表现出了不同的行为(多态)print('%s本月工资为: ¥%s元' %(emp.name, emp.get_salary()))if __name__ == '__main__':main()

python(11)—— 面向对象编程基础(对象,类,属性,封装,继承,多态)相关推荐

  1. python--编写程序:实现乐手弹奏乐器,乐手可以弹奏不同的乐器而发出不同的声音------使用类的封装继承多态的问题/使用面向对象的思想,设计自定义类,描述出租车和家用轿车的信息

    编写程序:实现乐手弹奏乐器,乐手可以弹奏不同的乐器而发出不同的声音 ------使用类的封装继承多态的问题 class Instrumnet():#乐器类def make_sound(self):pa ...

  2. Day07:常用模块,面向对象编程(对象类)及内置函数

    今日内容: 1.常用模块 2.面向对象编程(*****)     介绍面向对象编程     类     对象 3.内置函数 ------------------------------ 1.面向过程编 ...

  3. 【面向对象编程】(2) 类属性的定义及使用;__repr__()方法

    各位同学好,在上一节中我们学习了类实例化的基本方法:https://blog.csdn.net/dgvv4/article/details/122275348?spm=1001.2014.3001.5 ...

  4. [TS基础]对象,类,属性

    对象,类与属性 一.类(class) 1.属性与方法 2.构造器 3.继承 4.super关键字 二.抽象类与抽象方法 三.接口 四.属性的封装 五.泛型 笔记说明 一.类(class) 类可以理解为 ...

  5. 类的封装继承多态以及virtual interface-SV

    文章目录 一.面向对象 1.1术语 1.2 三大特性和五大原则 1.3 验证为什么需要OOP 二.类和对象 2.1浅复制shallow copy 2.2 深复制(deep copy) 三.类的封装和继 ...

  6. JAVA基础-U7 面向对象编程(基础部分)-类与对象

    类与对象(OOP) 快速入门 类是抽象的,概念的,代表一类事物.即它是数据类型 对象是具体的,实际的,代表一个具体事物.即它是实例 类是对象的模版,对象是类的一个个体,对应一个实例 养猫问题: 张老太 ...

  7. 面向对象编程——药品信息类的封装

    下面按照要求定义一个药品 Medicine 类. Medicine 类的属性如下: 药名 name 价格 price 生产日期 PD 失效日期 Exp Medicine 类的方法如下: 获取药品名称 ...

  8. C++基础:C++的封装/继承/多态

    封装(encapsulation):封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成"类",其中数据和函数都是 ...

  9. Java面向对象编程(基础部分)

    面向对象编程(基础部分) 类与对象 01: public class ObjectWorkDemo {public static void main(String[] args){Cat cat1 = ...

  10. Python零基础速成班-第10讲-Python面向对象编程(下),Property属性、特殊方法、设计模式、链表应用

    Python零基础速成班-第10讲-Python面向对象编程(下),Property属性.特殊方法.设计模式.链表应用 学习目标 面向对象编程 接上一讲:Property属性.特殊方法.设计模式 面向 ...

最新文章

  1. 想知道你在网上的发言,被怎么分析么?
  2. 基于plotly数据可视化_如何使用Plotly进行数据可视化
  3. python一个函数调用另一个函数的返回值_在另一个函数中使用返回值
  4. Linux 环境变量配置全攻略
  5. 学习Javascript闭包(Closure)(转载+理解心得)
  6. 以下属于4nf的分解为_数据库原理·模拟试卷及答案(1)
  7. 如何使用以太网将 Mac 接入互联网?
  8. 独家分享--48页PPT解密数据可视化!
  9. Ubuntu系统设置静态IP
  10. Linux下安装HP打印机的驱动程序
  11. Cortex-M3 (NXP LPC1788)之EEPROM存储器
  12. ZEMAX | 使用 Project Directory 组织 OpticStudio文件
  13. 欢迎空心字怎么写_春节快乐空心字怎么写
  14. 三星:大小屏QLED和OLED两手都要抓,都要硬
  15. 系统变慢,如何进行排查处理?
  16. linux opessl下载_linux Download openssl-1.0.2下载 openssl安装步骤
  17. LSTC模型的应用场景有哪些?
  18. 我的世界mod开发(6)无敌的护甲
  19. 全力冲unreal了
  20. 【量化】通过Fama-French三因子模型选股,收益能达到多少?

热门文章

  1. android极光推送声音,【极光推送】iOS APNS 自定义铃声
  2. android 手机内存64实际不到,为什么你的手机内存总是达不到64G?丢失的内存去哪了?详细解读...
  3. Jira的安装、使用与集成
  4. 0035【Python】小白学习Python大纲
  5. 汇编DOSBox安装及其常见指令(附安装包)
  6. NodeMCU文档中文翻译 4 烧写固件
  7. 每天学日语:日语输入法教程及日文键盘分部图
  8. tdd干扰波形_LTE中5大干扰源的产生分析
  9. HIPAA解决方案(三、270/271)
  10. 不会使用以下命令,别说你会Linux