Нельзя преобразовать тип a к b

Код примера:

type
  
  a = class

    x, y: Integer;

  end;
  
  b = class(a)

    z: Integer;

  end;

var
  s: array[1..2] of a;

begin
  
  s[1] := new a;

  s[2] := new b;
  
  foreach u: b in s do 

     write(u.z);
  
end.

при компиляции выдает ошибку в строке foreach:

test.pas(19) : Нельзя преобразовать тип a к b

Год назад, такая конструкция компилировалась и работала. Сейчас нет.

Что сломалось?

Ничего не сломалось, напротив, мы исправили ошибку. У Вас код ошибочный - он неявно преобразует a к b

Это понятно, но ведь как удобно было и как хорошо работало. :slight_smile: А теперь придется огород городить для того, чтобы выбрать нужные объекты в массиве и сделать с ними действия.

Кстати, а почему Вы говорите о неявном преобразовании. Ранее работало иначе. Из массива выбирались только те данные, которые соответствовали типу. А если так, то о каком преобразовании идет речь?

Возможно это Вам и удобно, когда кривой код работает, но быть этого не должно. Паскаль имеет жесткую типизацию; Вы определили в заголовке foreach переменную u типа b, компилятор пытается сгенерировать код для поочередного размещения в u элементов массива s, для чего выполняет присваивание b:=<элемент массива s>. Ничего удивительного, что компилятор не может “преобразовать тип a к b”.

Конечно, ничего удивительного. Сам в свое время удивился крутизне компилятора. Как он так делал и при этом правильно работал. Возможно, Вы сумеете объяснить, как раньше работало? Было бы познавательно.

Вижу такое решение вместо неработающего в настоящее время кода:

foreach u: a in s do

if u is b then 

  begin

    var w := u as b;

    write(w.z);

  end;

Есть какой-то более простой вариант?

Это правильный вариант. Ещё as возвращает nil если преобразование невозможно

1 лайк

А можно подробнее, в каких это случаях nil получается? К примеру тут ошибка компиляции:

type
  t1 = class end;
  t2 = class end;

begin
  var a: t1;
  var b := a as t2;
end.

Program1.pas(7) : Ожидался класс-потомок или класс-предок

Ну, написано: либо t1 либо t2 - потомки друг друга.

Нет, я понимаю что значит эта ошибка.

Но это то то в каком случае?

А, понял… В таком:

type
  t1 = class end;
  t2 = class end;

begin
  var a:object := new t1;
  var b := a as t2;
  writeln(b);
end.

Угу. nil будет

Если преобразовать нельзя