Почему определение класса в одной ячейке не распознает поля другого класса, созданные в другой ячейке?

Я использовал блокнот Polyglot Visual Studio Code и написал следующее в трех отдельных ячейках в порядке, указанном ниже.

Ячейка 1:

class Z;

Ячейка 2:

class A
{
    public static void f()
    {
        Console.WriteLine(Z.x);
    }
}

Ячейка 3:

class Z: A
{
    public static int x = 42;
}

Затем я выполнил ячейки по порядку и получил следующее сообщение об ошибке.

'Z' does not contain a definition for 'x'

Мой первоначальный вопрос был:

Возможно ли на C# написать (возможно, абстрактный) класс A, который имеет (возможно, статическую) функцию с сигнатурой void f(B b), типом параметра которой B является (возможно, абстрактный) класс, производный от A (class B: A {...})? Если нет, то почему?

и он назывался «Может ли класс C# использовать производный класс?»

Я принял ответ ниже, основанный на этой формулировке. Эта формулировка позже была удалена другим пользователем, который отредактировал мой вопрос и изменил его заголовок.

почему бы просто не попробовать это самому?

MakePeaceGreatAgain 15.07.2024 15:01

@MakePeaceGreatAgain Тот факт, что я не могу что-то сделать, не означает, что это невозможно сделать, и не объясняет, почему.

Evan Aad 15.07.2024 15:02

Итак, вы попробовали это? Какой код вы пробовали и какое сообщение об ошибке было?

Guy Incognito 15.07.2024 15:03
dotnetfiddle.net/rQrRqA
derpirscher 15.07.2024 15:04

это правда, но если вы попробовали это, скорее всего, вы уже ответили на вопрос. Что здесь определенно так.

MakePeaceGreatAgain 15.07.2024 15:06

Пожалуйста, уточните фразу «Я не могу что-то сделать». Похоже, вы что-то попробовали и получили ошибку.

MakePeaceGreatAgain 15.07.2024 15:09

Я попробовал это в блокноте Visual Studio Code Polyglot, написав классы в двух отдельных ячейках, и это не сработало. Но я думаю, если я напишу их обоих в одной ячейке, то это сработает.

Evan Aad 15.07.2024 15:10

и какая конкретно ошибка у тебя вылезла? «Не сработало» — это неправильное описание проблемы, оно может означать что угодно.

MakePeaceGreatAgain 15.07.2024 15:13

почему вы вообще использовали ячейку 1, если все равно определяете класс в ячейке 3? Я думаю, что когда вы удаляете ячейку1, она должна работать по назначению.

MakePeaceGreatAgain 15.07.2024 15:25

Если вы поместите все три части в одну ячейку, код будет недействителен, поскольку существует несколько объявлений класса Z. Если вы затем удалите начальный class Z;, код станет действительным и должен работать должным образом.

phuzi 15.07.2024 15:26

@MakePeaceGreatAgain Потому что я думал, что ошибка произошла из-за того, что класс A не знал о существовании класса Z.

Evan Aad 15.07.2024 15:27

@phuzi Да, это то, что я сделал. Я объединил ячейки 2 и 3 и выполнил эту объединенную ячейку.

Evan Aad 15.07.2024 15:28

@EvanAad, спасибо, что приняли мой ответ, основанный на исходном контексте вопроса. Однако в следующий раз я думаю, что вместо того, чтобы менять контекст, вам лучше просто задать новый вопрос.

wohlstad 15.07.2024 15:46

@MakePeaceGreatAgain Мне показалось, что я понял исходный вопрос, который кажется довольно прямолинейным, и ответил соответственно. Я не понимаю, почему вы думаете, что я поступил несправедливо. Как я уже упоминал выше, я считаю, что контекст вопроса не следует менять, чтобы сделать недействительными существующие ответы. Пожалуйста, объясните, где я вел себя несправедливо (я согласен, что здесь важно сохранять справедливое поведение) ?

wohlstad 15.07.2024 15:51

@wohlstad Я просто заметил: лично я упустил более широкую картину, поэтому проголосовал за закрытие. Если вы думаете, что вопрос был достаточно ясен, смело отвечайте – и, возможно, упустите суть. Я не хотел тебя обидеть.

MakePeaceGreatAgain 15.07.2024 15:56

@MakePeaceGreatAgain, никакого вреда не будет. Оглядываясь назад, я согласен, что более широкая картина действительно имела отношение к реальной проблеме, с которой столкнулся ФП. Но когда я прочитал это вначале, мне это показалось довольно простым.

wohlstad 15.07.2024 16:00
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
16
93
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Да, конечно. Это полностью справедливо:

class A
{
   public B GetDerived() => new B();
}

class B : A
{
   // ...
}

Разумеется, эти два класса должны находиться в одной сборке, поскольку им необходимо знать друг друга. Другой вопрос касается соответствующего варианта использования, который мне трудно представить. Обычно, если A является абстрактным, вы возвращаете A (которые тогда должны быть производными типами A), а не B, поскольку это не позволяет вам позже создать класс C, который является производным от A и который заменит B.

Ответ принят как подходящий

Да, это возможно.

Вот пример, который соответствует именно тому, что вы просили:

using System;

class A
{
    public void f(B b)
    {
        Console.WriteLine("in A.f.  b.Prop = " + b.Prop.ToString());
    }
}

class B : A
{
    public int Prop { get; set; } = 0;
}

class Program
{
    static void Main(string[] args)
    {
        B b1 = new B();
        b1.Prop = 1;
        B b2 = new B();
        b2.Prop = 2;
        b1.f(b2);
        A a = new A();
        a.f(b1);
    }
}

Выход:

in A.f.  b.Prop=2
in A.f.  b.Prop=1

Живая демонстрация

Примечание:
Поскольку вы спросили, A и/или B также могут быть абстрактными.


Обновление:
Вопрос был отредактирован после того, как был дан этот ответ, с добавлением дополнительных подробностей об использовании блокнота Полиглот.
По поводу этой дополнительной информации: проблема связана с тем, как блокнот выполняет ячейки одну за другой. Это не проблема, связанная с C# в целом или с использованием наследования в частности.

Блокнот выполняет ячейки одну за другой. Итак, когда вы выполняете ячейку 2, Z — это не что иное, как class, без какого-либо понятия x. Вот почему вы получаете ошибку.

Непонятно, какое поведение вы на самом деле хотите. Конечно, вы можете просто записать весь код в одну ячейку:

class A
{
    public static void f()
    {
        Console.WriteLine(Z.x);
    }
}    
class Z: A
{
    public static int x = 42;
}

Так что ваша проблема связана не с наследованием, а с тем, как Полиглот выполняет ячейки. Однако имейте в виду, что ваш подход довольно странный. Базовый класс никогда не должен делать никаких предположений о производных классах, он вообще не должен знать о существовании каких-либо производных классов. Однако это скорее концептуальная проблема, которая слишком широка для этого вопроса.

Кроме того (к ОП), обычно считается странным получать доступ к членам дочернего элемента из родительского (вызов Z.<anything> изнутри A). Возможно, вам захочется действительно спросить, почему вы это делаете, и, если возможно, провести рефакторинг.

gunr2171 15.07.2024 15:34

Другие вопросы по теме