首先,我知道我做不到,我认为这不是重复的问题(this 和 this 问题处理的是同一个问题,但他们只想解释为什么它不起作用) .
所以,我对类和继承有类似的概念,我会以某种方式优雅地做一些被禁止的事情。这是一个非常简单的代码片段,它反射(reflect)了我想要做的事情:
#include <iostream>
class A{
protected:
int var;
std::vector <double> heavyVar;
public:
A() {var=1;}
virtual ~A() {}
virtual void func() {
std::cout << "Default behavior" << this->var << std::endl;
}
// somewhere along the way, heavyVar is filled with a lot of stuff
};
class B: public A{
protected:
A* myA;
public:
B(A &a) : A() {
this->myA = &a;
this->var = this->myA->var;
// copy some simple data, e.g. flags
// but don't copy a heavy vector variable
}
virtual ~B() {}
virtual void func() {
this->myA->func();
std::cout << "This class is a decorator interface only" << std::endl;
}
};
class C: public B{
private:
int lotsOfCalc(const std::vector <double> &hv){
// do some calculations with the vector contents
}
public:
C(A &a) : B(a) {
// the actual decorator
}
virtual ~C() {}
virtual void func() {
B::func(); // base functionality
int heavyCalc = lotsOfCalc(this->myA->heavyVar); // illegal
// here, I actually access a heavy object (not int), and thus
// would not like to copy it
std::cout << "Expanded functionality " << heavyCalc << std::endl;
}
};
int main(void){
A a;
B b(a);
C c(a);
a.func();
b.func();
c.func();
return 0;
}
这样做的原因是我实际上是在尝试实现 Decorator Pattern (class B 有我要修饰的 myA 内部变量),但我也想使用 class A 的一些 protected 成员> 在进行“装饰”计算时(在 B 类 及其所有子类中)。因此,这个例子不是一个合适的装饰器例子(甚至不是一个简单的例子)。在示例中,我只专注于演示有问题的功能(我想使用但不能使用的功能)。在这个例子中甚至没有使用实现装饰器模式所需的所有类/接口(interface)(我没有抽象基类接口(interface),由具体基类实例继承以及一个抽象装饰器接口(interface),用作具体装饰器的父类(super class))。我只提到上下文装饰器(我想要一个 A* 指针的原因)。
在这种特殊情况下,我认为将(我的等价物)int var 公开(或者甚至编写可公开访问的 getter)有两个原因:
protected 变量,但不是变量值本身)protected 变量比 int 更难复制(它是 的二维 std::vector >doubles),并将其复制到派生类的实例中会不必要地耗费时间和内存现在,我有两种不同的方法让我的代码做我想做的事,但我都不喜欢它们,我正在寻找一个 C++ 概念实际上是为了做这种事情(我不是第一个想要这种行为的人)。
我目前拥有的以及为什么我不喜欢它:
<强>1。向基类声明所有(相关的)继承类 friend:
class A{
....
friend class B;
friend class C;
};
我不喜欢这个解决方案,因为它会迫使我每次编写新的子类时都修改我的基类,而这正是我的我试图避免。 (我只想在系统的主要模块中使用'A'接口(interface)。)
<强>2。将 A* 指针转换为继承类的指针并使用它
void B::func(){
B *uglyHack = static_cast<B*>(myA);
std::cout << uglyHack->var + 1 << std::endl;
}
变量名称非常暗示我使用这种方法的感受,但这是我现在正在使用的方法。由于我设计了这些类,所以我知道如何小心谨慎,只使用在 class A 中实际实现的内容,同时将其视为 class B。但是,如果其他人继续我的项目的工作,他可能对代码不太熟悉。此外,将变量指针转换到我非常清楚它不是的东西对我来说感觉纯粹是邪恶的。
我正在努力让这个项目的代码尽可能的漂亮和干净,所以如果有人对不需要不时修改基类或使用邪恶概念的解决方案有任何建议,我将不胜感激。
强>强>最佳答案
我确实相信您可能想重新考虑设计,但是我如何访问成员(member)? 的具体问题的解决方案可能是:
class A{
protected:
int var;
static int& varAccessor( A& a ) {
return a.var;
}
};
然后在派生类型中调用 protected 访问器,通过引用传递成员对象:
varAccessor( this->myA ) = 5;
现在,如果您正在考虑装饰器模式,我认为这不是可行的方法。
混淆的根源是大多数人没有意识到一个类型有两个独立的接口(interface),面向用户的 public 接口(interface)和用于实现提供者的 virtual 接口(interface)(即派生的类型),因为在许多情况下,函数既是public 又是virtual(即语言允许绑定(bind)两个语义不同的接口(interface))。在装饰器模式中,您使用基本接口(interface)来提供实现。继承是为了使派生类型可以提供通过一些实际工作(装饰)为用户操作,然后将工作转发给实际对象。继承关系不是让你通过 protected 元素以任何方式访问实现对象,这本身就是危险的。如果向您传递了一个派生类型的对象,该对象对 protected 成员具有更严格的不变性(即对于类型 X 的对象,var 必须是奇数),您采用的方法会让 < em="">装饰器(某种程度上)打破了应该被装饰的 X 类型的不变量。
关于c++ - 访问父类(super class)类型成员对象的 protected 成员——一个优雅的解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9946135/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信