精华内容
下载资源
问答
  • Java 重写Object类的常见方法

    千次阅读 2013-09-19 23:18:23
    当我们写一个的时候,都会对Java.lang.Object类的一些重要方法进行重写,这些方法包含:hashCode(),toString(),equals(),finalize(),clone(),wait(),notify()/notifyAll() 这八个方法。 一 Equals()方法: 1....
      当我们写一个类的时候,都会对
    Java.lang.Object类的一些重要方法进行重写,这些方法包含:hashCode(),toString(),equals(),finalize(),clone(),wait(),notify()/notifyAll() 这八个方法。 
    一 Equals()方法: 
    
    1.何时需要重写equals()
    当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念)。
    2.设计equals()
        [1]使用instanceof操作符检查“实参是否为正确的类型”。
        [2]对于类中的每一个“关键域”,检查实参中的域与当前对象中对应的域值。
        [2.1]对于非float和double类型的原语类型域,使用==比较;
        [2.2]对于对象引用域,递归调用equals方法;
        [2.3]对于float域,使用Float.floatToIntBits(afloat)转换为int,再使用==比较;
        [2.4]对于double域,使用Double.doubleToLongBits(adouble) 转换为long,再使用==比较;
        [2.5]对于数组域,调用Arrays.equals方法。 二 hashCode()方法:
    1.当改写equals()的时候,总是要改写hashCode()
    根据一个类的equals方法(改写后),两个截然不同的实例有可能在逻辑上是相等的,但是,根据Object.hashCode方法,它们仅仅是两个对象。因此,违反了“相等的对象必须具有相等的散列码”。
    2.设计hashCode()
       [1]把某个非零常数值,例如17,保存在int变量result中;
       [2]对于对象中每一个关键域f(指equals方法中考虑的每一个域):
    [2.1]boolean型,计算(f ? 0 : 1);
    [2.2]byte,char,short型,计算(int);
    [2.3]long型,计算(int) (f ^ (f>>>32));
    [2.4]float型,计算Float.floatToIntBits(afloat);
    [2.5]double型,计算Double.doubleToLongBits(adouble)得到一个long,再执行[2.3];
    [2.6]对象引用,递归调用它的hashCode方法;
    [2.7]数组域,对其中每个元素调用它的hashCode方法。
       [3]将上面计算得到的散列码保存到int变量c,然后执行 result=37*result+c;
       [4]返回result。 三 toString()方法: toString方法我们处处都用到,是一个很重点的小知识,这里大概讲一下:
    我们查阅API文档,查看java.lang.Object类的toString方法的详细描述是这样的:
    toString
    public String toString()
    Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.
    The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of: getClass().getName() + '@' + Integer.toHexString(hashCode()) Returns:
    a string representation of the object. 我们大概翻译一下:
    返回一个能够代表这个对象的字符串。一般而言,toString方法返回这个对象的“文本表达式”。这个返回的结果很简洁但是不是易于人们阅读的信息表达式。这里推荐大家在使用的子类的时候重写该方法。对于Object这个类而言,toString方法返回值是由所属类的类名、一个“@”符号和这个对象哈希码的无符号十六进制表达式组成的。换句话说,这个方法返回的字符串等同于下面的方法返回的值:     getClass().getName()+ '@' + Integer.toHexString(hashCode()) 返回:
        这个对象的字符串表达式我们再看看java.lang.String类中的toString方法,看看是否一样呢
    toString
    public String toString()
    This object (which is already a string!) is itself returned. Specified by:
    toString in interface CharSequence
    Overrides:
    toString in class Object
    Returns:
    the string itself. 我们还是翻译一下吧:
    这个对象自己(它已经是一个字符串了)就是返回值
    说明:
        CharSequence接口中的toString方法
    重写:
        重写了Object中的toString方法
    返回:
        自己本身的字符串我们可以看到,String类继承Object类,并且重写了toString方法,也就是说他有自己的toString方法,它返回一个自己本身的字符串,而自己本身就是字符串对象,这样就不会出现一推哈希码了。
    在这里为了更加明确,我们从“说明”中看到,String中toString方法是CharSequence接口的toString方法,那我们看一看java.lang.CharSequence接口的toString方法的定义:
    toString
    String toString()
    Returns a string containing the characters in this sequence in the same order as this sequence. The length of the string will be the length of this sequence. Overrides:
    toString in class Object
    Returns:
    a string consisting of exactly this sequence of characters 我们还是翻译一下:
    返回一个字符串,该字符串包含了与这个序列顺序相同的所有字符。字符串的长度就是该序列的长度重写:
    Object的toString
    返回:
    由该序列的特定的字符组成的字符串 四 clone()方法:
    对于克隆(Clone),Java有一些限制:
    1、被克隆的类必须自己实现Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。Cloneable 接口实际上是个标识接口,没有任何接口方法。
    2、实现Cloneable接口的类应该使用公共方法重写 Object.clone(它是受保护的)。
    3、在Java.lang.Object类中克隆方法是这么定义的:
    protected Object clone() throws CloneNotSupportedException
    创建并返回此对象的一个副本。表明是一个受保护的方法,同一个包中可见。
    按照惯例,返回的对象应该通过调用 super.clone 获得。
    浅拷贝:指的是你的类本身被拷贝,而没有拷贝类本身属性中的类。
    深拷贝:指的是包含类本身和属性类在内的所有类的拷贝。
    简单点说:就是浅拷贝的两个对象中的属性还会指向同一个类,而深拷贝则全部单独了。也就是说深拷贝把关联关系也拷贝了。可以简单理解为深拷贝中的数据类型中含有类类型的变量,因为java中传递参数的形式是以传值方式进行的。 五 finalize()方法: protected void finalize() throws Throwable { }:众所周知,finalize()方法是GC(garbage collector)运行机制的一部分 finalize()方法是在GC清理它所从属的对象时被调用的,如果执行它的过程中抛出了无法捕获的异常(uncaught exception),GC将终止对改对象的清理,并且该异常会被忽略;直到下一次GC开始清理这个对象时,它的finalize()会被再次调用。请看下面的示例:
    Java代码
    public final class FinallyTest {
    
    // 重写finalize()方法
    
    protected void finalize() throws Throwable {
    
    System.out.println("执行了finalize()方法");
    
    }
    public static void main(String[] args) {
    
    FinallyTest ft = new FinallyTest();
    
    ft = null;
    
    System.gc();
    
    }
    }

    运行结果如下:
    • 执行了finalize()方法
    程序调用了java.lang.System类的gc()方法,引起GC的执行,GC在清理ft对象时调用了它的finalize()方法,因此才有了上面的输出结果。调用System.gc()等同于调用下面这行代码:
    Java代码
    Runtime.getRuntime().gc();
    调用它们的作用只是建议垃圾收集器(GC)启动,清理无用的对象释放内存空间,但是GC的启动并不是一定的,这由JAVA虚拟机来决定。直到 JAVA虚拟机停止运行,有些对象的finalize()可能都没有被运行过,那么怎样保证所有对象的这个方法在JAVA虚拟机停止运行之前一定被调用呢?答案是我们可以调用System类的另一个方法:
    Java代码
    public static void runFinalizersOnExit(boolean value) {
    
    //other code
    
    }

    给这个方法传入true就可以保证对象的finalize()方法在JAVA虚拟机停止运行前一定被运行了,不过遗憾的是这个方法是不安全的,它会导致有用的对象finalize()被误调用,因此已经不被赞成使用了。
    由于finalize()属于Object类,因此所有类都有这个方法,Object的任意子类都可以重写(override)该方法,在其中释放系统资源或者做其它的清理工作,如关闭输入输出流。 六 wait()/notify()/notifyAll() 通常,多线程之间需要协调工作。例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕。如果图片还没有下载完,displayThread可以暂停,当downloadThread完成了任务后,再通知displayThread“图片准备完毕,可以显示了”,这时,displayThread继续执行。  以上逻辑简单的说就是:如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify.等待机制与锁机制是密切关联的。例如:
    synchronized(obj) {
    
    while(!condition) {
    
    obj.wait();
    
    }
    obj.doSomething();
    
    } 
      当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:
    synchronized(obj) {
    
    condition = true;
    
    obj.notify();
    
    }
      需要注意的概念是:  ◆调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {……} 代码段内。  ◆调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {……} 代码段内唤醒A。     ◆当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。  ◆如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。  ◆obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。  ◆当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。
    展开全文
  • PYTHON中的函数、静态函数、成员函数以及类变量、成员变量 Posted on 2019-03-16 15:10 Mr__Seven...2 classVar = ‘This is a class variable’ #类变量,可在函数或者成员函数中引用,为所有实例共有的 3 def ...

    PYTHON中的类函数、静态函数、成员函数以及类变量、成员变量
    Posted on 2019-03-16 15:10 Mr__Seven 阅读(14) 评论(0) 编辑 收藏
    复制代码
    1 class MethodDemo():
    2 classVar = ‘This is a class variable’ #类变量,可在类函数或者成员函数中引用,为所有实例共有的
    3 def init(self):
    4 self.instanceVar = ‘This is a instance variable’ #成员变量,只可在实例对象中引用,只属于当前实例
    5
    6 #成员函数
    7 def instanceMethod(self,x):
    8 temporaryVar = ‘This is a temporary variable’ #临时变量,只在当前函数有用,也就是该函数的局部变量
    9 print(‘executing instanceMethod(%s,%s)’%(self,x))
    10 print(‘classVar = %s’%self.classVar) #类变量可在成员函数中引用
    11 print(‘instanceVar = %s’%self.instanceVar) #成员变量可在成员函数中引用
    12 print(‘temporaryVar = %s’%temporaryVar) #临时变量只能在当前函数中引用
    13
    14 #类函数
    15 @classmethod
    16 def classMethod(cls,x):
    17 print(‘executing classMethod(%s,%s)’%(cls,x))
    18 print(‘classVar = %s’ % cls.classVar) #类方法中能引用类变量
    19 # print(‘instanceVar = %s’ % cls.instanceVar) #‘类函数不可引用成员变量 MethodDemo’ has no attribute ‘instanceVar’
    20 # print(‘temporaryVar = %s’ % temporaryVar) #类函数不可引用成员函数中的临时变量 name ‘temporaryVar’ is not defined
    21 # print(‘tempVar =%s’ % cls.tempVar) #类函数不可引用成员函数中的局部变量 ‘MethodDemo’ has no attribute ‘tempVar’
    22
    23 #静态函数
    24 @staticmethod
    25 def staticMethod(x):
    26 print(‘executing staticMethod(%s)’ % ( x))
    27 # print(‘classVar = %s’ % classVar) #静态函数不可引用类变量
    28 # print(‘instanceVar = %s’ % instanceVar) #静态函数不可引用成员变量
    29
    30 a = MethodDemo()
    31 a.instanceMethod(1) #实例对象可引用成员函数
    32 a.classMethod(1) #实例对象可引用类函数
    33 MethodDemo.classMethod(1) #类函数可直接通过类调用
    34 a.staticMethod(1) #静态函数可通过实例对象调用
    35 MethodDemo.staticMethod(1) #静态函数可直接通过类调用
    36
    37 print(a.instanceMethod)
    38 print (a.classMethod)
    39 print (a.staticMethod)
    复制代码
    运行结果:

    executing instanceMethod(<main.MethodDemo object at 0x00000000023C0B70>,1)
      classVar = This is a class variable
      instanceVar = This is a instance variable
      temporaryVar = This is a temporary variable
      executing classMethod(<class ‘main.MethodDemo’>,1)
      classVar = This is a class variable
      executing classMethod(<class ‘main.MethodDemo’>,1)
      classVar = This is a class variable
      executing staticMethod(1)
      executing staticMethod(1)
      <bound method MethodDemo.instanceMethod of <main.MethodDemo object at 0x00000000023C0B70>>
      <bound method MethodDemo.classMethod of <class ‘main.MethodDemo’>>
      <function MethodDemo.staticMethod at 0x00000000024DE048>

    由此可看出,python中的变量主要包括:类变量、成员变量以及临时(局部)变量。其中类变量可以在类函数、成员函数中直接使用,可以通过类名或者实例对象直接调用。成员变量只可以在成员函数中使用,并且只能通过实例对象调用。而函数内部定义的临时变量只能在当前函数中使用。

    至于类函数、静态函数、成员函数之间的区别如下:

    类函数,通过装饰器@classmethod注解的函数为类函数,有一个隐含参数cls是该类本身。顾名思义,为这个类拥有的函数,可以直接通过类名直接调用,无需实例化对象,也可以通过该类的实例对象调用。

    静态函数,通过装饰器@staticmethod注解的函数为静态函数,可以通过类名直接调用,也可以通过该类的实例化对象调用。其实静态方法只是在类的作用域里的函数而已,一般主要处理与这个类的逻辑关联, 如验证数据。

    成员函数,有一个隐含参数self是当前实例本身。只能被该类的实例对象调用。

    展开全文
  • 如果我们用全局变量会破坏数据的封装,一般的用户代码都可以修改这个全局变量,这时可以的静态成员来解决这个问题。 非static数据成员存在于类型的每个对象中,static数据成员独立该的任意对象存在,它是与...

    一、static 成员变量

    对于特定类型的全体对象而言,有时候可能需要访问一个全局的变量。比如说统计某种类型对象已创建的数量。
    如果我们用全局变量会破坏数据的封装,一般的用户代码都可以修改这个全局变量,这时可以用类的静态成员来解决这个问题。
    非static数据成员存在于类类型的每个对象中,static数据成员独立该类的任意对象存在,它是与类关联的对象,不与类对象关联。

    (1)、static成员的定义

    static成员需要在类定义体外进行初始化与定义

    (2)、特殊的整型static const成员

    整型static const成员可以在类定义体中初始化,该成员可以不在类体外进行定义

    (3)、static成员优点:

    static成员的名字是在类的作用域中,因此可以避免与其它类成员或全局对象名字冲突。

    可以实施封装,static成员可以是私有的,而全局对象不可以

    阅读程序容易看出static成员与某个类相关联,这种可见性可以清晰地反映程序员的意图。


     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #ifndef _COUNTED_OBJECT_H_
    #define _COUNTED_OBJECT_H_

    class CountedObject
    {
    public:
        CountedObject();
        ~CountedObject();
    public:
         static  int GetCount();
    private:
         static  int count_;       // 静态成员的引用性声明
    };


    #endif  // _COUNTED_OBJECT_H_


     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include  "CountedObject.h"

    int CountedObject::count_ =  0;       // 静态成员的定义性声明

    CountedObject::CountedObject()
    {
        ++count_;
    }

    CountedObject::~CountedObject()
    {
        --count_;
    }

    int CountedObject::GetCount()
    {
         return count_;
    }

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include  "CountedObject.h"
    #include <iostream>
    using  namespace std;

    int main( void)
    {
         //cout<<CountedObject::count_<<endl;
        cout << CountedObject::GetCount() << endl;
        CountedObject co1;
         //cout<<CountedObject::count_<<endl;
        cout << CountedObject::GetCount() << endl;
        CountedObject *co2 =  new CountedObject;
         //cout<<CountedObject::count_<<endl;
        cout << CountedObject::GetCount() << endl;
         delete co2;
         //cout<<CountedObject::count_<<endl;
        cout << CountedObject::GetCount() << endl;

    }

    上述程序定义一个静态成员变量和静态成员函数,可以通过类名:: 访问static 成员变量,也可以通过非/静态成员函数访问。


    二、static 成员函数

    static成员函数没有隐含的this指针
    非静态成员函数可以访问静态成员
    静态成员函数不可以访问非静态成员


     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #include <iostream>
    using  namespace std;

    class Test
    {
    public:
        Test( int y) : y_(y)
        {

        }
        ~Test()
        {

        }

         void TestFun()
        {
            cout <<  "x=" << x_ << endl;  //OK,非静态成员函数可以访问静态成员
            TestStaticFun();
        }
         static  void TestStaticFun()
        {
            cout <<  "TestStaticFun ..." << endl;
             //TestFun();        Error,静态成员函数不能调用非静态成员函数
             //cout<<"y="<<y_<<endl;     Error,静态成员函数不能访问非静态成员
        }
         static  int x_;       // 静态成员的引用性说明
         int y_;
    };

    int Test::x_ =  100;      // 静态成员的定义性说明

    int main( void)
    {
        cout <<  sizeof(Test) << endl;

         return  0;
    }

    三、使用C++设计一个类,该类最多能被实例化3次且不能被继承

    1. /*用C++实现一个LimitedClass类,该类最多只能被实例化三次,且不能被继承*/  
    2. #include <iostream>  
    3. using namespace std;  
    4.   
    5. class LimitedClass  
    6. {  
    7. public:  
    8.     static LimitedClass* getInstance();  
    9.     static void setCnt(int);//设置能实例化的次数  
    10.     ~LimitedClass();  
    11.     //其它方法;  
    12. private:  
    13.     LimitedClass();//私有构造函数,无法被继承  
    14.     static int cnt;//实例化次数  
    15. };  
    16.   
    17. int LimitedClass::cnt=0;//实例化次数类外定义  
    18. LimitedClass* LimitedClass::getInstance()  
    19. {  
    20.     if(cnt>0)  
    21.     {  
    22.         --cnt;  
    23.         return new LimitedClass();  
    24.     }  
    25.     else  
    26.         return NULL;  
    27. }  
    28.   
    29. LimitedClass::LimitedClass()  
    30. {  
    31.     cout<<"LimitedClass Constructor!!!"<<endl;  
    32. }  
    33.   
    34. LimitedClass::~LimitedClass()  
    35. {  
    36.     cout<<"LimitedClass Destructor!!!"<<endl;  
    37. }  
    38.   
    39. void LimitedClass::setCnt(int n)  
    40. {  
    41.     cnt=n;  
    42. }  
    43. //测试程序  
    44. int main()  
    45. {  
    46.     LimitedClass::setCnt(3);  
    47.     LimitedClass *l1=LimitedClass::getInstance();  
    48.     LimitedClass *l2=LimitedClass::getInstance();  
    49.     LimitedClass *l3=LimitedClass::getInstance();  
    50.     if (l1!=NULL && l2!=NULL && l3!=NULL)  
    51.     {  
    52.         cout<<"实例化成功3个对象"<<endl;  
    53.     }  
    54.     LimitedClass *l4=LimitedClass::getInstance();  
    55.     if (NULL==l4)  
    56.         cout<<"第四个实例无法实例化"<<endl;  
    57.   
    58.     delete l1;  
    59.     delete l2;  
    60.     delete l3;  
    61.     return 0;  
    62. }  

    展开全文
  • 实例

    千次阅读 2016-05-03 10:10:26
    面向对象最重要的概念就是(Class)和实例(Instance),必须牢记是抽象的模板,比如Student,而实例是根据创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。 仍以Student...
    面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
    

    仍以Student类为例,在Python中,定义类是通过class关键字:

    class Student(object):
          name = 'c'
          score  = 100
    class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,继承的概念我们后面再讲,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。
    定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:
    >>> bart = Student()
    >>> bart
    <__main__.Student object at 0x10a67a590>
    >>> Student
    <class '__main__.Student'>
    可以看到,变量bart指向的就是一个Student的实例,后面的0x10a67a590是内存地址,每个object的地址都不一样,而Student本身则是一个类。
    可以自由地给一个实例变量绑定属性,比如,给实例bart绑定一个name属性:
    >>> bart.name = 'Bart Simpson'
    >>> bart.name
    'Bart Simpson'
    由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:
    class Student(object):
    
        def __init__(self, name, score):
            self.name = name
            self.score = score
    注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
    有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:
    >>> bart = Student('Bart Simpson', 59)
    >>> bart.name
    'Bart Simpson'
    >>> bart.score
    59
    和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。
    数据封装
    面向对象编程的一个重要特点就是数据封装。在上面的Student类中,每个实例就拥有各自的name和score这些数据。我们可以通过函数来访问这些数据,比如打印一个学生的成绩:
    >>> def print_score(std):
    ...     print('%s: %s' % (std.name, std.score))
    ...
    >>> print_score(bart)
    Bart Simpson: 59
    但是,既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在Student类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法:
    class Student(object):
    
        def __init__(self, name, score):
            self.name = name
            self.score = score
    
        def print_score(self):
            print('%s: %s' % (self.name, self.score))
    要定义一个方法,除了第一个参数是self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入:
    >>> bart.print_score()
    Bart Simpson: 59
    这样一来,我们从外部看Student类,就只需要知道,创建实例需要给出name和score,而如何打印,都是在Student类的内部定义的,这些数据和逻辑被“封装”起来了,调用很容易,但却不用知道内部实现的细节。
    封装的另一个好处是可以给Student类增加新的方法,比如get_grade:
    class Student(object):
        ...
    
        def get_grade(self):
            if self.score >= 90:
                return 'A'
            elif self.score >= 60:
                return 'B'
            else:
                return 'C'
    同样的,get_grade方法可以直接在实例变量上调用,不需要知道内部实现细节:
    >>> bart.get_grade()
    'C'
    小结
    类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;
    方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;
    通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。
    和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:
    >>> bart = Student('Bart Simpson', 59)
    >>> lisa = Student('Lisa Simpson', 87)
    >>> bart.age = 8
    >>> bart.age
    8
    >>> lisa.age
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute 'age'

    展开全文
  • Python——实例

    千次阅读 2018-08-22 23:44:05
    一. 的定义 在Python中,定义是通过class关键字。 语法格式如下: ...class后面紧接着是类名,类名通常是大写开头的单词,紧接着是(object),表示该是从哪个继承下来的,通常,如果没...
  • python学习——实例

    千次阅读 2016-07-13 08:42:54
    面向对象最重要的概念就是(Class)和实例(Instance),必须牢记是抽象的模板,比如Student,而实例是根据创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。 仍以...
  • FLEX的Object类

    千次阅读 2013-07-18 09:53:15
    ActionScript 3.0 中的 Object数据类型与早期版本中的 Object 数据类型存在以下三方面的区别:第一,Object 数据类型不再是指定给没有类型注释的变量的默认数据类型。第二,Object 数据类型不再包括 ...
  • Java静态内部实例化问题

    万次阅读 2015-12-15 15:56:21
    静态内部类可以实例化! 1.首先在外部中的static方法中不能使用普通内部,因为内部必须要与外部建立关联才能使用,可以说是同生共死。 2.我在编码过程中,需要2个共同完成一个功能,其中一个工具只...
  • python中的类变量

    万次阅读 2018-04-24 17:44:35
    python中的类变量最近我参加了一次面试,面试官要求用python实现某个api,一部分代码如下class Service(object): data = [] def __init__(self, other_data): self.other_data = other_data 面试官说:“ data =...
  • java理解实例成员

    万次阅读 2017-12-11 13:49:19
    类变量的蓝图中创建一个对象,每个对象都有自己的变量的唯一拷贝。例如Bicycle实例变量是cadence, gear, speed。每个Bicycle对象的每个变量都有...这些变量是通过类关联的,而不是任何对象。的每个实例
  • OC 关联对象(Associated Object

    千次阅读 2015-07-21 19:23:15
    在一个已有的的类目中添加公开属性或者是私有属性,常规的做法是无法实现的,这个涉及到Runtime的机制关于变量的存储方式,在实例化之后,成员变量在内存中的位置就被初始化好了,无法动态的添加。 但是,有一...
  • 我们上节提到了,使用property函数定义的属性不要与内已经定义的普通实例变量重名,如果是重名会发生什么呢?本案例通过这个例子一是说明重名可能产生的后果,也想说明property定义属性在内访问会遇到什么情况。...
  • 使用Category可以很方便地为现有的增加方法,但却无法直接增加实例变量(有为此使用查表法的,也算曲线救国吧)。不过从Mac OS X v10.6开始,系统提供了Associative References,这个问题就很容易解决了。 我...
  • Java加载过程和对象实例化详解

    千次阅读 2017-11-19 17:21:28
    Java虚拟机加载过程 加载时机 加载过程 –加载 –验证 –准备 –解析 –初始化 1、加载时机  从被加载虚拟机内存中开始,到卸载出内存为止,他的整个生命周期包括:加载、验证、准备、解析、初始化...
  • 变量分为 实例变量(不带static的变量) 和 类变量(带static的变量) 使用同步的原因 1. 在系统中对访要使用多线程进行访问; 2. 在该中有 类变量, 或者是 在的方法中有访问 公共资
  • 深入理解Java加载器(ClassLoader)

    万次阅读 多人点赞 2017-06-26 09:34:08
    【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) ...关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解
  • iOS - 分类添加属性之关联引用

    千次阅读 2016-09-04 22:52:55
    虽然不能增加实例变量,但是添加属性还是可以的,只不过需要自己在分类中实现get和set方法,同时标记属性为动态获取。 其中一种方法叫做关联引用,实现了用存取器来访问属性,当然实际上并没有实例变量,所以本质上...
  • AS3.0 Object 作为关联数组

    千次阅读 2014-06-04 22:53:39
     Object使用字符串作为key,即使你使用了其他类型的数据作为key,Object也会将使用该key的toString方法得到其字符串表示作为key来存储,也就是说Object使用toString方法进行键的比较。 var a:Object = new ...
  • 目录 面向对象编程 常用术语/名词解释 ...初始化:通过调用对象来创建实例 __init__()“构造器”方法 __new__()“构造器”方法 __del__()“解构器”方法 实例属性 在构造器中首先设置实例属性 默认参
  • 技术-流程变量

    2007-09-06 13:49:00
    流程变量定义流程变量分成3种流程变量全局变量(全局流程变量)全局临时变量(全局流程临时变量)局部变量(流程某个接点内有效的变量)see org.jbpm.context.exe.ContextInstance目前还没有使用过局部变量(流程...
  • JAVA中实例与Class对象

    千次阅读 2019-03-22 14:29:41
    简单理解,就是new,就是对实例化,创建这个对应的实际对象,只是对事物的描述,而实例化就相当于为这个描述新开辟了一块内存,可以改变这块区域里的各种属性(成员变量),当然,也可以实例化多块区域,...
  • Python——属性/实例属性

    万次阅读 2014-03-19 22:25:12
    数据属性仅当需要有更加“静态”数据类型时才变得有用,它和任何实例都无关。  1. 的数据属性  数据属性仅仅是所定义的变量。这种属性已被 OO 程序员所熟悉,即静态变量,或者是静态数据。它们表示这些...
  • 作者:egg邮箱:xtfggef@gmail.com微博:http://weibo.com/xtfggef博客:...包含:基本语法,,内部,继承相关,异常,线程,集合,io,虚拟机等。本篇题目整理时参照了传智播客(http://www.itcast.cn)的一篇面试
  • Swift动态获取成员变量及对象关联

    千次阅读 2015-10-16 21:57:52
    1.动态获取成员变量,以tabBarItem.badgeValue为例,由于Oc中的写法和Swift中的写法类似,这里就不写Oc的Demo了 self.tabBarItem.badgeValue = "10" //拿到显示badgeValue的控件 //1拿到tabbar for tabBarChild in ...
  • /* 经评论区提醒。一开始的重载写错了,应该为重写。 重载:多态的一种表现。 重写:方法覆盖。...例如定义实例对象Data,这个实例对象用于处理year,month,day三个元素。 Data a = new Data(); D...
  • [ObjectC]Runtime 运行时之一:与对象

    千次阅读 2016-05-17 00:33:06
    这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现等。 这种特性意味着Objective-C不仅需要一个编译器,还需要一个运行时系统来执行编译的代码。...
  • 目录 官方解析 博主栗子 关于QMetaObject::className()的栗子 官方解析 Qt元对象系统提供了信号与槽机制,通过信号与槽实现对象间的通信,RTTI,以及动态属性...2.Q_OBJECT宏放在的私有部分,这个宏可以带来m...
  • 父类与子类关系继承关系抽象接口多态 多态的体现多态的前提多态的好处多态的弊端 多态中成员的特点Object 父类与子类关系:继承关系   继承通过extends 关键字来声明: 子类 extends 父类  继承的作用 ...
  • Java顶级父类Object

    千次阅读 2018-01-05 16:03:54
    一、定义(一)什么是object类 1.Object类存储在java.lang包中,使用的时候无需显示导入,编译时由编译器自动导入。...Object类变量只能用作各种值的通用持有者,要对他们进行任何专门的操作,都需要知道它们...
  • 学习面向对象分析(OOD)与面向对象设计(OOD),在获取并列出概念之后,必须要明确之间的关系。这些关系由弱到强大致分为一下几种:依赖、关联、聚合、组合、继承。下面将分别以我最简单的语言进行概述。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 142,731
精华内容 57,092
关键字:

object类的变量可以关联任何类的实例