开发者社区


项目管理 | IT/商务管理 | 职涯
首页 - 管理和职涯
管理&职涯
全文搜索:   

OOP: 限制对象属性的访问
作者:
2001-10-19 18:49:11



请尽量使用封装机制
在任何程序风格中,尤其是在面向对象的编程中,将暴露的编程界面背后的实现细节隐藏起来是非常关键的.这使得低层的实现方法能够在不影响编程界面现有的客户端的前提下改变,而且能使对象完全自主的管理它们自己的状态.

分离界面和实现方法的第一步就是隐藏类的内部数据.要使一个成员变量或是方法对Java中所有潜在的客户不可见,可以将用private关键字将它声明为私有成员变量,如下所示:

private int customerCount;

要使一个成员变量或是方法除了其本身所属类的子类以外对Java中所有潜在的客户不可见可以使用protected关键字将它声明成保护类型的,如下所示:

protected int customerCount;

要使一个成员变量或是方法除了其本身所属的类以外对Java中所有潜在的客户不可见不使用任何关键字来声明它,如下所示:

int customerCount;

要将一个成员变量或是方法暴露给其所属类的所有客户,可以用public关键字将它声明为公共的成员变量,如下所示:

public int customerCount;


访问成员变量
不论一个对象的数据隐藏得多么好,客户仍然需要访问一些隐藏的数据.这是通过调用函数或方法来实现的.在Java中,使用特殊的被称做属性访问器的方法来访问隐藏的数据是可能的.在Java中属性访问器和通常的函数之间并没有本质的区别.将一个通常的方法转变成一个属性访问器唯一要做的事情就是参照一个命名规则来添加方法.

读数据的访问器的命名规则就是将方法命名为和数据域一样的名字,将首字母大写,然后在方法名字的前面添加get或是is."写"数据访问器的命名规则就是将方法命名为和数据域一样的名字,将首字母大写,然后在方法名字的前面添加set.下面的例子演示了写和读数据的数据访问器方法.

这是一个"读"数据访问器方法:

public int getCustomerCount()
{
    return(customerCount);
}


这是另一个"读"数据访问器方法

public int isCustomerActive()
{
    return(customerActive);
}

这是一个"写"数据访问器方法:

public void setCustomerCount(int newValue)
{
    customerCount = newValue;
}

使用访问器方法允许其它对象访问一个对象的隐藏数据而不直接涉及数据域.这就允许拥有隐含数据的对象在改变成员变量以前做正确性检查并控制成员变量是否应该被设置成新的值.

现在让我们修改例子程序来使用这些概念,如所示.

public class HelloWorld
{
    public static void main(String[] args)
    {
        Dog animal1 = new Dog();
        Cat animal2 = new Cat();
        Duck animal3 = new Duck();
        animal1.setMood(Animal.COMFORTED);
        System.out.println("A comforted dog says " +animal1.getHello());
        animal1.setMood(Animal.SCARED);
        System.out.println("A scared dog says " +animal1.getHello());
        System.out.println("Is a dog carnivorous? " +animal1.isCarnivorous());
        System.out.println("Is a dog a mammal? " +animal1.isCarnivorous());
        animal2.setMood(Animal.COMFORTED);
        System.out.println("A comforted cat says " +animal2.getHello());
        animal2.setMood(Animal.SCARED);
        System.out.println("A scared cat says " +animal2.getHello());
        System.out.println("Is a cat carnivorous? " +animal2.isCarnivorous());
        System.out.println("Is a cat a mammal? " +animal2.isCarnivorous());
        animal3.setMood(Animal.COMFORTED);
        System.out.println("A comforted duck says " +animal3.getHello());
        animal3.setMood(Animal.SCARED);
        System.out.println("A scared duck says " +animal3.getHello());
        System.out.println("Is a duck carnivorous? " +animal3.isCarnivorous());
        System.out.println("Is a duck a mammal? " +animal3.isCarnivorous());
    }
}

abstract class Animal
{
    // The two following fields are declared as public because they need to be
    // accessed by all clients
    public static final int SCARED = 1;
    public static final int COMFORTED = 2;
    // The following fields are declared as protected because they need to be
    // accessed only by descendant classes
    protected boolean mammal = false;
    protected boolean carnivorous = false;
    protected int mood = COMFORTED ;
    public boolean isMammal()
    {
        return(mammal);
    }

    public boolean isCarnivorous()
    {
        return(carnivorous);
    }

    abstract public String getHello();

    public void setMood(int newValue)
    {
        mood = newValue;
    }

    public int getMood()
    {
        return(mood);
    }
}


interface LandAnimal
{
    public int getNumberOfLegs();
    public boolean getTailFlag();
}

interface WaterAnimal
{
    public boolean getGillFlag();
    public boolean getLaysEggs();
}

class Dog extends Animal implements LandAnimal
{
    // The following fields are declared private because they do not need to be
    // access by any other classes besides this one.
    private int numberOfLegs = 4;
    private boolean tailFlag = true;
    // Default constructor to make sure our properties are set correctly
    public Dog()
    {
        mammal = true;
        carnivorous = true;
    }
    // methods that override superclass's implementation
    public String getHello()
    {
        switch (mood) {
            case SCARED:
                return("Growl");
            case COMFORTED:
                return("Bark");
        }
        return("Bark");
    }

    // Implementation of LandAnimal interface

    public int getNumberOfLegs()
    {
        return(numberOfLegs);
    }

    public boolean getTailFlag()
    {
        return(tailFlag);
    }
}

class Cat extends Animal implements LandAnimal
{
    // The following fields are declared private because they do not need to be
    // access by any other classes besides this one.
    private int numberOfLegs = 4;
    private boolean tailFlag = true;
    // Default constructor to make sure our properties are set correctly
    public Cat()
    {
        mammal = true;
        carnivorous = true;
    }
    // methods that override superclass's implementation
    public String getHello()
    {
        switch (mood) {
            case SCARED:
                return("Hiss");
            case COMFORTED:
                return("Purr");
        }
        return("Meow");
    }

    // Implementation of LandAnimal interface
    public int getNumberOfLegs()
    {
        return(numberOfLegs);
    }

    public boolean getTailFlag()
    {
        return(tailFlag);
    }
}

class Duck extends Animal implements LandAnimal, WaterAnimal
{
    // The following fields are declared private because they do not need to be
    // access by any other classes besides this one.
    private boolean gillFlag = false;
    private boolean laysEggs = true;
    private int numberOfLegs = 2;
    private boolean tailFlag = false;
    // Default constructor to make sure our properties are set correctly
    public Duck()
    {
        mammal = false;
        carnivorous = false;
    }
    // methods that override superclass's implementation
    public String getHello()
    {
        switch (mood) {
            case SCARED:
                return("Quack, Quack, Quack");
            case COMFORTED:
                return("Quack");
        }
        return("Quack");
    }

    // Implementation of WaterAnimal interface

    public boolean getGillFlag()
    {
        return(gillFlag);
    }

    public boolean getLaysEggs()
    {
        return(laysEggs);
    }

    // Implementation of LandAnimal interface

   
public int getNumberOfLegs()
    {
        return(numberOfLegs);
    }

    public boolean getTailFlag()
    {
        return(tailFlag);
    }
}



这个程序的输出结果应该如下:
A comforted dog says Bark
A scared dog says Growl
Is a dog carnivorous? true
Is a dog a mammal? true
A comforted cat says Purr
A scared cat says Hiss
Is a cat carnivorous? true
Is a cat a mammal? true
A comforted duck says Quack
A scared duck says Quack, Quack, Quack
Is a duck carnivorous? false
Is a duck a mammal? false

总结
使用数据隐藏/封装机制是一个控制对象数据和状态的强有力的方法.它允许一个对象决定是否要改变一个成员变量和如何改变一个成员变量.这使得一个对象的实现细节能够改变而暴露的对象界面得以维持.在我们的下一篇文章中,我们将进一步探讨Java提供的变量作用域规则并开始学习Java对象是如何构造和初始化的.

【上一页】
声明:
Builder.com.cn(原ZDNet China应用开发频道)原创文章版权所有,未经许可严禁转载,且不构成投资建议。
近期相关报道:
实用技术文档
J2me XML
C/C++ C#
Java Oracle
Mysql .Net
VB.NET CSS
SQL Server 数据库
SQL UNIX
Linux Jsp
PHP Perl
Javascript IIS
XHTML ColdFusion
ASP/ASP.NET Apache
AJAX
订阅技术邮件
订阅"技术圈"杂志!请在下面选择您感兴趣的专题,填写e-mail地址,然后按订阅按钮:
应用开发管理
VS.NET 周刊
Database 周刊
WEB Service周刊
JAVA 周刊
IT 认证
Windows服务器周刊
互联网开发
当Windows Server 2008专家得5000元现金大奖
CNET NETWORKS 中国: 爱卡汽车网 | CNET科技资讯网 | e询网 | CWEEK | 蜂鸟网 | GameSpot China | 个人电脑 | PChome | SPN | 网友世界 | ZDNet China | 中关村在线
CNET NETWORKS 美国: BNET | CNET.com | CNET Download.com | CNET News.com | CNET Reviews | CNET Shopper.com | GameSpot | MP3.com | mySimon | Release 1.0 | Search.com | TechRepublic | TV.com | Webshots | ZDNet
Copyright (c) 2006 CNET Networks 版权所有。 ZDNet 是CNET Networks公司注册服务商标。
ZDNet 公司标识是 CNET Networks公司注册服务商标。
中华人民共和国电信与信息服务业务经营许可证编号:京ICP证010391号