Java C+中的set/get方法+;

Java C+中的set/get方法+;,java,c++,conventions,Java,C++,Conventions,Java程序员和API似乎更喜欢显式的set/get方法 但是,我觉得C++社区对这样的实践感到不快。 如果是这样的话,有没有一个特殊的原因(除了更多的代码行)为什么会这样 另一方面,为什么Java社区选择使用方法而不是直接访问 谢谢 在C++中显式设置/get方法没有什么不寻常。我已经看到了它的大量C++,它可以非常有用的不允许直接访问数据成员。< / P> < P>我不认为C++社区不赞成使用GETSter和SETTER。它们几乎总是一个好主意。< P>检查一下为什么java倾向于它们,C+

Java程序员和API似乎更喜欢显式的set/get方法

但是,我觉得C++社区对这样的实践感到不快。 如果是这样的话,有没有一个特殊的原因(除了更多的代码行)为什么会这样

另一方面,为什么Java社区选择使用方法而不是直接访问


谢谢

在C++中显式设置/get方法没有什么不寻常。我已经看到了它的大量C++,它可以非常有用的不允许直接访问数据成员。< / P> < P>我不认为C++社区不赞成使用GETSter和SETTER。它们几乎总是一个好主意。

< P>检查一下为什么java倾向于它们,C++的原因是相同的。简而言之:它允许您更改访问数据成员的方式,而无需强制重新编译客户端代码(使用您的代码的代码)。它还允许您强制执行特定的策略,以了解如何访问数据以及访问数据时要执行的操作。

通过强制使用set/get方法,可以在getter/setter中实现有用的副作用(例如,当get/set的参数是一个对象时).

反对get/set方法的通常论点是,如果您同时拥有这两种方法,并且它们只是微不足道的
返回x
x=y那么你实际上根本没有封装任何东西;您还可以将成员公开,这样可以节省大量样板代码

显然,在某些情况下,它们仍然有意义;如果您需要在它们中做一些特殊的事情,或者您需要使用继承,特别是接口

如果实现getter/setter,则可以在以后更改它们的实现,而无需修改使用它们的代码。我想你提到的对它的不满是一种事情,如果没有人期望以这种方式改变函数,那么拥有它们就没有什么好处。在许多情况下,您可以稍后处理更改实现的情况


<>我不知道C++社区对Java社区的支持程度比java社区还要低或更少;我的印象是,在Python等语言中,它们的用法并不太常见。

< P>作为一般语言概念的属性在技术上早于C++,例如SimultTalk,但它们从来都不是标准的一部分。吸气剂和定位器是C++在开发UI时使用的概念,但事实上,开发UI是一个昂贵的命题,它是一种有效的系统语言。C++中的GETTER和SETTER的一般问题是,由于它们不是标准,所以每个人都有不同的标准。 在系统语言中,效率关注点很高,那么就更容易公开变量本身,尽管有很多文献强烈反对这种做法。通常,您只看到C++对象实例之间的信息交换比简单的项目更丰富。 <>你可能会对这个问题有很多观点,但是一般来说,C++是指做对象的C,让OOP访问不知道对象的开发者。要将虚拟和模板引入到语言中已经够难了,我认为它已经停滞了一段时间

Java的不同之处在于,在一开始,Java引入了垃圾收集等领域,因此更容易推广健壮封装的理念,即外部实体应该让它们肮脏的小爪子远离类的内部元素

<>我承认这是非常有意思的——在这个时候,我用C++来优化3D图形管道之类的高度优化的东西——我已经需要管理我所有的对象内存,所以我会从根本上看不实用的代码,只是用来存储更多的函数来存储访问。运行时(如MSFT.net ILM)的基本性能能力使其有时难以防御


纯粹是我的2c,它与面向对象编程的基础有关——向用户隐藏对象的内部。对象的用户不需要知道(也不应该关心)对象的内部结构

它还使您可以控制对象的用户尝试对其进行读/写时所执行的操作。实际上,您向对象的用户公开了一个接口。它们必须使用该接口,并且您可以控制调用该接口中的方法时发生的事情——getter和setter将是接口的一部分


它只是让调试变得更容易。一个典型的场景是,当您的对象以一种奇怪的状态着陆时,您正在调试以了解它是如何到达那里的。您所要做的就是在getter和setter中设置断点,并假设其他一切都正常,您就可以看到对象如何进入奇怪的状态。如果对象的用户都在直接访问其成员,那么确定对象的状态何时发生更改变得非常困难(尽管并非不可能)

一个设计良好的类在理想情况下不应该有太多的get和set。在我看来,太多的get和set基本上表明了一个事实,即其他人(可能还有很多人)需要我的数据来实现他们的目的。在这种情况下,为什么这些数据首先属于我?这违反了封装的基本原则(一个逻辑单元中的数据+操作)


<> P> C++,在没有技术限制和(实际上丰富)“设置”和“获取”方法的情况下,如果你想在系统中的太多其他实体使用的java接口中有太多的“GET”和“SET”,那么你应该暂停并重新设计一下。 在Java中,如果您从裸字段访问开始,后来又改变了主意,转而使用getter/setter,那么很容易找到所有
template <class T>
class DefaultPredicate
{
public:
  static bool CheckSetter (T value)
  {
    return true;
  }
  static void CheckGetter (T value)
  {
  }
};

template <class T, class Predicate = DefaultPredicate <T>>
class Property
{
public:
  operator T ()
  {
    Predicate::CheckGetter (m_storage);
    return m_storage;
  }
  Property <T, Predicate> &operator = (T rhs)
  {
    if (Predicate::CheckSetter (rhs))
    {
      m_storage = rhs;
    }
    return *this;
  }
private:
  T m_storage;
};
class Test
{
public:
  Property <int> TestData;
  Property <int> MoreTestData;
};

int main ()
{
  Test
    test;

  test.TestData = 42;
  test.MoreTestData = 24;
  int value = test.TestData;
  bool check = test.TestData == test.MoreTestData;
}
class NoErrorHandler
{
public:
  static void SignalError (const char *const error)
  {
  }
};

class LogError
{
public:
  static void SignalError (const char *const error)
  {
    std::cout << error << std::endl;
  }
};

class Exception
{
public:
  Exception (const char *const message) :
    m_message (message)
  {
  }

  operator const char *const ()
  {
    return m_message;
  }

private:
  const char
    *const m_message;
};

class ThrowError
{
public:
  static void SignalError (const char *const error)
  {
    throw new Exception (error);
  }
};

template <class ErrorHandler = NoErrorHandler>
class RGBValuePredicate : public DefaultPredicate <int>
{
public:
  static bool CheckSetter (int rhs)
  {
    bool
      setter_ok = true;

    if (rhs < 0 || rhs > 255)
    {
      ErrorHandler::SignalError ("RGB value out of range.");
      setter_ok = false;
    }

    return setter_ok;
  }
};
class Test
{
public:
  Property <int, RGBValuePredicate <> > RGBValue1;
  Property <int, RGBValuePredicate <LogError> > RGBValue2;
  Property <int, RGBValuePredicate <ThrowError> > RGBValue3;
};

int main ()
{
  Test
    test;

  try
  {
    test.RGBValue1 = 4;
    test.RGBValue2 = 5;
    test.RGBValue3 = 6;
    test.RGBValue1 = 400;
    test.RGBValue2 = 500;
    test.RGBValue3 = -6;
  }
  catch (Exception *error)
  {
    std::cout << "Exception: " << *error << std::endl;
  }
}