【问题标题】:Is there anyway to use the property like behavior?反正有没有使用类似行为的属性?
【发布时间】:2017-10-30 17:43:52
【问题描述】:

我有以下公式

X := X + F*(1-i div n);

在哪里

X, F, i, n: integer;

我使用的代码是这样的

F := 7; // the initial speed with no friction.
n := 10; // the animation number of steps.
Hn := n * 2 ; 
X := 0;  // first Pos
i := 1;  
J := 1;
while J < Hn do
begin
  X := X + F * (1 - i div n);
  if X > Xmax then X := 0;  <-- line (1).
  if i >= n then Dec(i)
  else Inc(i);
  Inc(J); 
end;

如果可能的话,我想使用它但没有类/记录实现(不在类/记录实现/方法内)。不是确切的语法,只是相同的原理,而不是直接分配给 X,SetX 是调用然后将结果分配给 X。

X: integer write SetX; // This is not a correct delphi syntax. I added it to explain the behavior I want. 

function SetX(aValue: integer): integer;
const
  Xmax: SomeIntegerValue;
begin
  if aValue > Xmax then result := 0  
  else result := aValue; 
end;

所以我可以省略第 (1) 行。如果可能,公式后面的所有行都将被省略,while 循环将如下所示

while J < Hn do  // J will be incremented each time the loop wants to read it.    
begin
  X := X + F * (1 - i div n);
end;

是否有使用类似行为的属性?

注意:我正在寻找一种方法来改变变量的赋值和读取方式,就像您在记录/类的属性中所做的那样。

【问题讨论】:

  • 我会在这里使用IfThen
  • 如果您的循环也在记录方法中,您仍然可以仅对 X := X + F * (1 - i div n); 进行正确处理,我认为这是实现这一点的最佳方式。
  • 我不确定你所说的通用是什么意思,你仍然需要把它放在一些程序中。您在代码中的唯一区别是,您将编写 MyRecord.MyProcedure,而不是像 MyProcedure 那样调用它。其他一切都一样。
  • @EugeneK 我知道这一点(阅读我的第一条评论或第二条注释)。我想我在上一条评论中也解释了 universal
  • 编程到语言中。你逆流而上。不。使用本地函数。无论如何,它会更加明确和清晰。这是一个更好的解决方案。

标签: delphi properties delphi-10-seattle


【解决方案1】:

有没有在类/记录之外使用类似属性的方法?

不可以,属性 getter 和 setter 只能在记录和类中实现。

【讨论】:

  • 大卫,我知道这一点。我在问是否有任何方法可以获得相同的输出(使用汇编或任何其他方式来改变变量 X 的分配和读取方式)
  • 我理解你的问题。答案是不。故事结束。
  • 大卫。请看我的回答。我想知道你对此的看法。感谢您的帮助。
  • 大卫,对不起,我的母语不是英语。这个骇人听闻的词是不是很好地表示shocked :)。
  • 不,我的意思是被吓坏了。这是对语言的严重滥用。
【解决方案2】:

你可以使用像这样的本地函数

procedure YourProcedure;

var
  X: Integer;
  LJ: Integer;
function J: Integer;
begin
  Inc(LJ);
  Result := LJ;
end; 
procedure SetX(const AValue: Integer);
const
  Xmax: SomeIntegerValue;
begin
  if aValue > Xmax then X := 0  
  else X := aValue; 
end;
//...
begin
  while J < Hn do  // J will be incremented each time the loop wants to  read it.    
  begin
     SetX(X + F * (1 - i div n));
  end
end.

【讨论】:

  • LJ 必须在第一次调用 J 之前显式初始化。不幸的是,这破坏了这种方法的美丽和权宜之计。
  • Eugenek,请看我的回答。
【解决方案3】:

我找到了一种方法来做我想做的事。我知道重载 := 运算符是不可能的,但是强制编译器产生与重载运算符相同的行为是可能的。

重载不会让我控制 LSA(左侧参数)。但它完全控制将任何TType(在我的情况下是integer)隐式转换为TXinteger。所以我所要做的就是确保每个运算符都会生成TType,这将强制编译器将其隐式转换为TXinteger

每次它想给TXinteger 赋值时强制编译器使用我的隐式运算符意味着我控制了赋值因此我重载了:= 运算符。

以下是一个可以省略 Line(1) 的测试示例。

program Project4;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;



type
   TXinteger = record
     X: integer;
     class operator Add(a, b: TXinteger): integer;
     class operator Add(a: TXinteger; b:integer): integer;
     class operator Add(a: integer; b:TXinteger): integer;
     class operator Implicit(a: Integer): TXinteger;
     class operator Implicit(a: TXinteger): Integer;
   end;

// Example implementation of Add
class operator TXinteger.Add(a, b: TXinteger): integer;
begin
  result := a.X + b.X;
end;(**)

class operator TXinteger.Add(a: TXinteger; b:integer): integer;
begin
  result := a.X + b;
end;

class operator TXinteger.Add(a: integer; b:TXinteger): integer;
begin
  result := a + b.X;
end;

class operator TXinteger.Implicit(a: Integer): TXinteger;
const
  Xmax: integer = 10;
begin
  if a > Xmax then result.X := 0 else result.X := a;
end;

class operator TXinteger.Implicit(a: TXinteger): Integer;
begin
  result := a.X;
end;

var
X: TXinteger;
Hn, F, i,J, n: integer;
begin
  try
  F := 7;
  n := 10;
  Hn := n * 2 ;
  X := 0;
  i := 1;
  J := 1;
  while J < Hn do
    begin
    X := X + F * (1 - i div n);
    // Line (1)  is gone now.
    if i >= n then Dec(i)
    else Inc(i);
    Inc(J);
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

注意:在这种情况下,仅仅为了省略一行代码而做所有这些是没有意义的。我想分享这个,因为它让我们了解如何重载 := 运算符。

我想要的是这样的:

  • 改变X:Integer 的读取方式(从变量x 的存储中读取的值)。
  • 更改X:Integer 的分配方式。

通过重载所有使用 X 值的运算符,我完成了第一个。 并且通过如上所述强制编译器,我完成了第二个。

感谢大家的帮助。

【讨论】:

  • 如果我理解的问题正确,它需要一个没有任何“类/记录实现”的解决方案。但是,此代码使用对记录变量的赋值,因此无法满足问题中的要求。
  • @SertacAkyuz 没有任何“类/记录实现”意味着(至少对我而言)。不在记录/类实现/方法中。
  • 我看到了编辑,答案仍然无法满足要求,运算符重载方法仍然属于该记录。
  • @SertacAkyuz 那么我不接受它作为答案的决定是正确的。这是我发现的唯一可以完成这项工作的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-18
  • 2017-12-30
  • 2021-01-12
相关资源
最近更新 更多