type
TRec=record
a:Integer;
b:Integer;
end; TA=class(TObject)
private
FABC:TRec;
public
constructor Create;
......
property ABC:TRec read FABC;
end;constructor TA.Create;
begin// 下面语句编译不能通过
ABC.a:=10; // Left side cannot be assigned to
ABC.b:=10; // Left side cannot be assigned to // 但你只要这样写,却可以顺利通过编译
// 这可能影响到我们的类的健壮性。
with ABC do
begin
a:=10;
b:=10;
end;
end;
TRec=record
a:Integer;
b:Integer;
end; TA=class(TObject)
private
FABC:TRec;
public
constructor Create;
......
property ABC:TRec read FABC;
end;constructor TA.Create;
begin// 下面语句编译不能通过
ABC.a:=10; // Left side cannot be assigned to
ABC.b:=10; // Left side cannot be assigned to // 但你只要这样写,却可以顺利通过编译
// 这可能影响到我们的类的健壮性。
with ABC do
begin
a:=10;
b:=10;
end;
end;
解决方案 »
- 请Delphi前辈帮看看《TeeChart组件快速实现测井曲线显示》中的图像是如何实现的!
- 批量压缩oracle表中存储图片blob字段的保存问题
- 在RichEdit中如何获得总行数?
- 无法回复,无法显示 XML 页 ,lonaerd,我要例子,[email protected]
- 如何用编程为listbox1添加一项或多项内容?
- 怎样让treeview中不同级的节点按不同的规则排序?
- 关于OpenDialog.....(很菜的问题)
- 为什么打不开Word
- 在报表中打印预览的时候,将打印的按钮屏蔽,只能预览,不能打印?
- Delphi 的帧包的问题
- 三层结构中,要限定AP SERVER只处理特定类型的任务,如何实现?
- intraweb如何在一个TIWAppForm中显示另一个TIWAppForm(或TFrame)
property ABC:TRec read FABC;应该是:
property ABC:TRec read FABC write FABC;吧?没有write怎么赋值啊!
不过,你如何想到用with的?佩服!
constructor TA.Create;
var
X:TRec;
begin
X:=ABC;
X.a:=10;
X.b:=10;
FABC: TRec;这个。
就是TLISTVIEW地问题。。
增加数据地时候,如果直接是add地花好像不能很好地控制数据
如下; listitems:=lv1.Items.Add;
with listitems do
begin
caption:=aq1.Fields[2].Value;
SubItems.Add(aq1.Fields[0].value);
end;
aq1.Next;
我也不知道什么原因。我想应该是with地用法了。。
关注中
ABC.a:=10; 是毫无问题的。因为虽然属性中定义ABC是只读的,只是表明ABC的值——对于对象而言就是指向对象实例的一个引用——是不可更改的。所以下面的代码:
ABC.a := 10; //正确,注意ABC的值(对象的地址)没有改变,只是改变了对象实例中的值;
ABC := TRec.Create; //错误,不能改变这个引用指向的地址;现在回头再看使用Record的情况,直接写:
ABC.a := 10; //ABC.a编译器认为是向一个无法更改的变量中赋值,所以出错
with ABC do
a := 10; //这时候的a是指ABC所在内存中a这个位置的值,是一个可以更改的数值,所以没有出错,很类似对象的处理方式所以我认为这是Delphi在实现中的一个不一致的情况,亏楼主这么细心发现了。不过要说对封装性的影响,我觉得是根本就不应该声明结构类型的只读属性。如果Delphi定义为直接赋值是可行的我认为也没什么错。
再看数组的情况,声明为
TIntArray = array[0..10] of Integer;
property Something TIntArray read FSomething;
那么其实是不能控制数组中的值为只读的,所以Delphi提供了这样定义的方式
property Something[Index: Integer] read GetSomething;
这样对这个列中的每个值的读写都是通过类的方法来处理的,而不是通过数据结构。
同样的道理,上面如果要实现封装,应该分别声明a, b在类中,或者暴露出一个具有只读属性a,b的类来控制a,b的读写(不过Delphi没有友元,直接向Unit中的其他对象的私有数据赋值觉得很不爽)
你的说法有点道理,如果编译器不能识别,只能通过我们程序员来控制了,也就是不提供这种形式的只读属性了。
不要当普通的变量来思维~~
当取属性值的时候就是调用了GetXXX~~
当写属性值的时候就是调用了SetXXX~~type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
function GetPoint: TPoint;
{ Private declarations }
public
{ Public declarations }
property Point: TPoint read GetPoint;
end;
//....
procedure TForm1.Button1Click(Sender: TObject);
begin
// Point.X := 1; //这是不能通过编译的~~
with Point do begin //这不也可以,就当成GetPoint
X := X + 1;
Y := Y + 1;
end;
end;function TForm1.GetPoint: TPoint;
begin
Result := Mouse.CursorPos;
end;
//................property ABC: TRec read FABC;with ABC do //就相当于with Get(FABC) do ~~
FABC:Integer;
public
property ABC:Integer read FABC write FABC;再有,你没有理解我的意思,我认为在我提出的问题中,用了 with 也不应当编译通过,因为这是一个只读的属性
//实际是对FABC开域了(开了FABC内存地址)~~
//通过这种方法确实能给只读的属性赋值~~//请做如下测试~~
property Int: Integer read FInt;
end;
//..
procedure TForm1.Button1Click(Sender: TObject);
var
I: PInteger;
begin
I := Pointer(@Int);
I^ := 1234;
Caption := IntToStr(FInt);
end;
//同样可以给一个不是结构类型的只读属性赋值~~
//同样取Int属性的值时,是把FInt的地址给取了过来~~//继续研究下~~
如果直接通过私有成员,是存在隐患的。用这种方式编的代码是不是会有安全漏洞啊?:)
procedure TForm1.Button1Click(Sender: TObject);
const
C: Integer = 123;
begin
PInteger(@C)^ := 456;
Caption := IntToStr(C);
end;说道安全漏洞:
估计这也只能在自己写的程序码中实现~~
破坏的也只是自己的程序……
修改内存的工具很多~~
很多的游戏玩家就会~~
所以写象登陆等软件时~~
不要把密码暴露在内存里!~~