我的 Getter/Setter 方法会在设置/返回值之前检查该值。当值无效时,它们会抛出异常(BadArgumentException 或 IllegalStateException)。这是必需的,因为我们使用无效值初始化所有成员 - 因此我们避免使用这些无效值(== 在其他地方出现错误/段错误/异常)。
好处是:
- 当您从模型中收到成员值时,您就知道它们是有效的
- 有效性检查仅在模型对象中执行
- 取值范围在模型对象中定义
这似乎很不寻常,因为大多数新团队成员首先提示它 - 即使在我向他们解释后他们同意我的看法。
问题:这是一种好的编程风格吗? (虽然浪费了一点性能)
示例代码:
inline bool MyClass::HasGroupID const { return m_iGroupID != 0; }
int MyClass::GetGroupID() const
{
if( !HasGroupID() )
throw EPTIllegalStateException( "Cannot access uninitialized group ID!" );
return m_iGroupID;
} // END GetGroupID() const
void MyClass::SetGroupID( int iGroupID )
{
// negative IDs are allowed!
if( iGroupID != 0 )
throw EPTBadArgumentException( "GroupID must not be zero!", iGroupID );
m_iGroupID = iGroupID;
} // END SetGroupID( int )
用法:
// in serialization
if( myObject.HasGroupID() )
rStream.writeAttribute( "groupid", GetGroupID() );
// in de-serialization
try {
// required attribute - throw exception if value is invalid
myObject.SetGroupID( rStream.GetIntegerAttribute( "groupid" );
} catch( EPTBadArgumentException& rException )
{
throw EPTBadXmlAttribute( fileName, rException );
}
最佳答案
我认为这是常见的风格,而且它肯定是第一个想法中 getter/setter 的核心动机之一。但是,在您的特定示例中,我认为它们没有意义,而且我认为通常有更好的选择:
如果在 HasGroupID
返回 false 时调用 GetGroupID
引发异常,那么这是一个程序员错误 - 因此您可能应该使用 assert
。事实上,为什么一开始就有可能没有组 ID 的对象呢?这听起来像是一个有点不雅的设计。
此外,如果只有非零 ID 有效,那么您应该尝试使用专用类型更早地实现此限制。这样,所有处理组 ID 的代码都可以确保 ID 有效(事实上,编译器会强制执行此操作!)并且您不可能忘记在某个地方进行检查。考虑:
class GroupID {
public:
explicit GroupID( int id ) : m_id( id ) {
if ( m_id == 0 ) {
throw EPTBadArgumentException( "GroupID must not be zero!", m_id );
}
}
// You may want to allow implicit conversion or rather use an explicit getter
operator int() const { return m_id; }
};
使用这个,你可以写
void MyClass::SetGroupID( GroupID id )
{
// No error checking needed; we *know* it's valid, because it's a GroupID!
// We can also use a less verbose variable name without losing readability
// because the type name reveals the semantics.
m_iGroupID = id;
} // END SetGroupID( int )
事实上,由于组 ID 现在是一种专用类型,您可以将函数重命名为 Set
并使用重载。所以你有 MyClass::Set(UserID)
和 MyClass::Set(GroupID)
等等。
关于c++ - "Value Validation in Getter/Setter"是好的样式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8179239/