面向对象(一)【“类与对象”的概念及特性】

面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是种具有对象概念的程序编程范式,同时也是一种程序开发的抽象方针。在此不再累述编程范式的种种类别,重点讨论“类与对象”概念及特性。

1 类与对象的概念

类(class): 对一类具有相同属性的对象的抽象。比如,牧羊犬、金毛、哈士奇都可抽象为“狗”类。类的定义包含了数据的形式以及对数据的操作。
对象(object): 类的实例,每个对象都是其类中的一个实体。比如,我家的狗名字叫buck, 那么buck这条活生生的狗就是“狗”这个类的实例。

我们来看一下python中是如何定义一个类的:

# 定义一个 Dog 类
class Dog:

    def __init__(self, name):
        self.name = name

    def talk(self):
        print("[{}]:Wang Wang Wang.".format(self.name))

# 创建对象buck
buck = Dog("buck")
# 调用对象中的talk()方法
buck.talk()

对上述定义类的代码中的某些关键字进行简单阐述:

定义类: 通过class这个关键字定义一个类,类名叫Dog。
属性: name变量就是Dog这个类封装的一个属性。
方法: talk()函数就是Dog这个类中的方法。
self: 注意这是个特殊参数,当类实例化之后self即是对象本身。
创建对象:在类名之后添加括号,传入需要的参数,就创建了一个对象。
访问对象中的属性或方法:通过 对象.属性 或者 对象.方法 的形式。
__init__():类的构造函数,创建对象会调用该方法,后面会详细解释。

简单了解了类与对象的概念、定义类,创建对象、属性和方法等之后,我们接着阐述面向对象的三大特性:封装、继承、多态。

2 封装性

属性和方法都叫类的成员。封装(Encapsulation)是通过限制只有特定类的对象可以访问这一特定类的成员,其中有两点需要注意:

一是类抽象出一些成员封装在某个地方;二是通过某种形式可以访问这些成员。

下面的代码定义了一个Person类, 封装了人的name, age,还有一个自我介绍的hello() 方法。

class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def hello(self):
        print("Hello, my name is %s, i‘m %s years old" % (self.name, self.age))

# 封装到某处
person1 = Person("YouYuan Liu", 25)
person2 = Person("Jeo Chen", 38)

# 访问属性
print(person1.name)    # YouYuan Liu
print(person2.name)    # Jeo Chen

# 访问方法
person1.hello()        # Hello, my name is YouYuan Liu, i‘m 25 years old
person2.hello()        # Hello, my name is Jeo Chen, i‘m 38 years old 

2.1 封装到某处

当执行 person1 = Person("YouYuan Liu", 25)时,self 等于 person1,并把 "YouYuan Liu" 和 25 分别封装到了self/person1 的name和age中;
当执行 person2 = Person("Jeo Chen", 38)时,self 等于 person2, 并把 "Jeo Chen" 和 38 分别封装到了self/person1 的name和age中。

2.2 访问封装的内容

(1)访问属性

通过 对象.属性 的方式访问,如person1.name就是访问之前封装的person1这个对象的name属性,即"YouYuan Liu"。

(2)访问方法

通过 对象.方法  的方式访问,如person1.hello() 访问到了hello()方法,hello中调用了self.name 和self.age,实际上此处self=person1,通过self间接访问了属性。

3 继承性

3.1 单继承

继承性(Inheritance)是指,在某种情况下,一个类会有“子类”。子类比原本的类(称为父类)要更加具体化。例如上例 “人(Person)”这个类,它可能会有“男人类(Man)”、“女人类(Woman)”这两个子类。
子类会继承父类的属性和行为,并且也可包含它们自己的。如女人类(Woman),会继承人(Person)的“姓名name”、“年龄age”以及“自我介绍hello()”等成员,也有自己独有的成员“生孩子birth_children()”。
下列代码演示了Python语法怎么实现继承:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def hello(self):
        print("Hello, my name is %s, i‘m %s years old" % (self.name, self.age))

class Man(Person):
    def __init__(self, name, age):
        # 继承的第一种写法
        Person.__init__(self, name, age)

class Woman(Person):
    def __init__(self, name, age):
        # 继承的第二种写法
        super(Woman, self).__init__(name, age)

    def birth_children(self, p):
        print("[{}] birthed [{}]".format(self.name, p))

注意上述两种继承的写法。子类既继承了父类的所有成员,又有自己的独有成员:

man1 = Man("YouYuan Liu", 25)
woman1 = Woman("Jeo Chen", 38)
print(man1.name)     # YouYuan Liu
man1.hello()         # Hello, my name is YouYuan Liu, i‘m 25 years old
print(woman1.age)    # 38

woman1.birth_children("little Jeo")   # [Jeo Chen] birthed [little Jeo]

3.2 多继承

继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能。Python中是支持多重继承的,此处我们着重谈一下面试常考的多重继承顺序。

(1)在Python3中多继承

写下如下代码:

class A:
    def run(self):
        print("run A")

class B(A):
    def run(self):
        super(B, self).run()
        print("run B")

class C(A):
    def run(self):
        super(C, self).run()
        print("run C")

class D(B, C):
    def run(self):
        super(D, self).run()
        print("run D")

class E(B, C):
    pass

a = A()
b = B()
c = C()
d = D()
e = E()

接下来我们运行:

b.run()
# run A
# run B

这里不难理解,因为在class B 的run()方法中,显式地调用了其父类(class A)的run()方法,所以,会先执行类A的run()方法,然后再执行类B的run()方法。

那我们接着运行下面的代码:

d.run()
# run A
# run C
# run B
# run D

这就有点难以理解了。按照我们“正常的思维”理解:调用D中的run()方法,不是应该找D的父类B的run()方法,然后B中的run()调用其父类A中的方法run()了吗,那么顺序应该是run A-->run B -->run D啊,这里第二个位置怎么多了个run C 呢?
这是为什么?为什么?Why?
这是因为Python3中的多继承是按照"广度优先"(Breadth-First Search)顺序继承的。什么是广度优先呢?我们将上面的A/B/C/D类继承关系画成一颗树:

广度优先,就意味着继承顺序变成了D ---> B ---> C ---> A。展开而言,当调用D中的run(),由于D中run()主动调用父级run()即B中run();B中run()主动调用父级run()即C中run();C中run()主动调用父级run()即A中run()。所以自然打印顺序就成了:

run A ---> run C ---> run B ---> run D

好了,那么思考一下下面的代码会打印什么呢,你能解释打印结果吗?

 e.run()

(2)Python2中的多继承

在Python2中,经典类和新式类的继承顺序不同,经典类是按照深度优先顺序,而新式类是按照广度优先的。
Python 2.x中默认都是经典类,只有显式继承了object才是新式类。

# python2.x中:

# 经典类 默认
class A:
    pass

# 新式类
class A(object):
    pass

Python 3.x中默认都是新式类,不必显式的继承object。

# python3.x中:

# 以下均是新式类
class A:
    pass

class A(object):
    pass

4 多态性

多态(Polymorphism)是指由继承而产生的相关的不同的类,其对象对同一消息会做出不同的响应。例如,狗和猫都有“叫()”这一方法,但是调用狗的“叫()”,狗会汪汪叫;调用猫的“叫()”,鸡则会喵喵叫。
在Python中崇尚鸭子类型:

class Dog(object):
    def talk(self):
        print("Wang wang!")

class Cat(object):
    def talk(self):
        print("Miao miao~~")

def animal_talk(obj):
    obj.talk()

dog = Dog()
cat = Cat()
animal_talk(dog)
animal_talk(cat)
# Wang wang!
# Miao miao~~

有种“一个接口,多种实现”的感觉。

5 面向对象的优势

(1)程序的解耦  (2)代码的可复用 性 (3)代码清晰,易于理解,便于维护。

假设现在我们要实现一个人的自我介绍,那么我们对比一下,不用面向对象,和用面向对象,有啥区别:

5.1 不用面向对象

def talk(name, age, city):
    print("I am {}, {} years old, from {}".format(name, age, city))

talk("Liu yi fei", 30, "BJ")
talk("Liu you yuan", 25, "HB")
talk("Jeo Chen", 38, "TW")

5.2 面向对象

class Person(object):
    def __init__(self, name, age, city):
        self.name = name
        self.age = age
        self.city = city

    def talk(self):
        print("I am {}, {} years old, from {}".format(self.name, self.age, self.city))

obj1 = Person("Liu yi fei", 30, "BJ")
obj1.talk()
obj2 = Person("Liu you yuan", 25, "HB")
obj2.talk()
obj3 = Person("Jeo Chen", 38, "TW")
obj3.talk()

这样一看,不用面向对象似乎代码更短、更简洁? 那为啥还要用面向对象?
但是, 我们想想啊,假设还有500个人,另外还有跑步run(),吃eat(),睡sleep()等10种方法。
不用面向对象的话,1个人的10中方法就会重复写10次:方法("name", "age", "city")了;而面向对象只需要写一次。当然这只是一个简单例子罢了,面向对象的优势远不止这些,在此不再多说。

6 小结

类: 对一类具有相同属性的对象的抽象,如哈士奇、金毛都可抽象为狗类。

对象:类的实例。狗类的一个实例,如我家的狗 buck。

面向对象的三大特性:封装、继承、多态。

原文地址:https://www.cnblogs.com/zingp/p/8584323.html

时间: 2024-10-30 16:05:06

面向对象(一)【“类与对象”的概念及特性】的相关文章

C#面向对象基础--类与对象

1.类与对象 类是面向对象编程的基本单元:类造出来的变量叫对象. 一个类包含俩种成员:字段与方法. 字段即变量,方法即函数. 面向对象思想:教给我们如何合理的运用类的规则去编写代码. 2.类的字段 字段代表了类中的数据.在变量之前可以加上public.private和protected表示字段的访问权限. 3.类的方法 (1).函数的概念 表达式: 返回值类型  方法名(参数列表) { 语句1: 语句2: ..... return 表达式: } 函数需要向外界返回一个值,由return语句实现.

Day16:面向对象编程——类和对象

一.面向对象的程序设计 在此之前用到的事面向过程的程序设计,它的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比设计好一条流水线,考虑周全什么时候处理什么东西. 优点:极大的降低了程序的复杂度 缺点是:一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得是大改,改一个组件,牵一发而动全身. 应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等. 面向对象的程序设计的核心是对象.程

面向对象、类与对象、成员与局部变量、封装、private、构造函数、this、static、extends、super、final、abstract、interface、多态、内部类、异常【5】

  本文原创作者:pipi-changing本文原创出处:http://www.cnblogs.com/pipi-changing/ 本文版权归作者和博客园共有,未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接 ,否则保留追究法律责任的权利. 面向对象概念 理解面向对象 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 •强调的是功能行为 面向对象 •将功能封装进对象,强调具备了功能的对象. 面向对象是基于面向过程的. 面向过程   在一个结构体中定义窗口的大小

面向对象基础——类与对象的定义

面向对象的概念 封装性:对外部不可见.可以保护程序中的某些内容. 继承性:扩展功能的. 类与对象的关系: 定义类和对象的方法? 类图的画法:Person类图 分为三层: 第一层表示类的名称,类的名称与之前一样要求开头首字母大写. 第二层表示属性的定义,按照" 访问权限 属性名称:属性类型 " 的格式定义: 第三层表示类中方法的定义,按照"  访问权限 方法名称():方法返回值类型  " 的格式定义.如下图所示: 类与对象的进一步研究 掌握Java中的内存划分,jav

Day28:面向对象编程——类和对象

一.面向对象的程序设计 在此之前用到的事面向过程的程序设计,它的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比设计好一条流水线,考虑周全什么时候处理什么东西. 优点:极大的降低了程序的复杂度 缺点是:一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得是大改,改一个组件,牵一发而动全身. 应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等. 面向对象的程序设计的核心是对象.程

Python 面向对象(创建类和对象,面向对象的三大特性是指:封装、继承和多态,多态性)

概念:                                                                                                                                                     ·        面向过程:根据业务逻辑从上到下写垒代码 ·        函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 ·        面向对象:对函数进行分类和封装,

Chapter 1. 面向对象(类、对象、字段、方法、属性、构造函数)

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 面向对象 { //创建person类 public class person { //Fields:字段 private string _name; private int _age; private char _gender; //Properties:属性 public string Name { ge

面向对象(类与对象)

类与对象 在现实世界中:肯定是先有对象,再有类 世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,比如 人类.动物类.植物类等概念.也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在,比如你无法告诉我人类 具体指的是哪一个人 在程序中:务必保证先定义类,后产生对象 这与函数的使用是类似的:先定义函数,后调用函数,类也是一样的:在程序中需要先定义类,后调用类.不一样的是:调用 函数会执行函数体代码返回的是函数体执行的结果,而调用类会

面向对象、类与对象

面向对象 方法:java中,用来完成解决某件事或实现某个功能的方法 格式: 修饰符 返回值类型 方法名(参数类型 参数名1,参数类型  参数名2,....){ 执行语句 ..... return 返回值; } class 里面只有两种东西  属性和方法 类与对象 创建对象的格式 类名 对象名 = new 类名(): public class Car { String color; int number; void run() { System.out.println(color + ":&quo