Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > Общие вопросы .NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.02.2015, 10:15   #1
hoz
Форумчанин
 
Аватар для hoz
 
Регистрация: 29.06.2013
Сообщений: 132
По умолчанию О надобность приведения к типу

Я уже прошёл эту тему по сути. Но очередной раз столкнувшись призадумался и не понял надобности такого подхода. Зачем создавать переменную типа базового класса, хранящую ссылку на экземпляр производного класса?
Например,
PHP код:
BaseClass instance = new DerivedClass(); 
По сути, дочерний класс получает всю информацию о базовом классе, а наоборот не возможно. Получается, переменная типа базового класса, хранящая ссылку на экземпляр производного класса не знает ничего о методах производного класса, и, тогда какой смысл так делать? Ведь данная переменная instance не сможет вызвать никакое поле или метод из производного класса. В чём смысл?
Проще тогда сразу создать переменную базового типа, хранящую ссылку на экземпляр базового класса. В таком случае тоже данной переменной будут доступны только поля и методы базового класса... Почему нет?

Последний раз редактировалось hoz; 07.02.2015 в 10:25.
hoz вне форума Ответить с цитированием
Старый 07.02.2015, 10:41   #2
Selestis
Форумчанин
 
Аватар для Selestis
 
Регистрация: 21.01.2009
Сообщений: 719
По умолчанию

Представьте классический пример: вы пишете классы геометрических фигур.
Пусть будет Circle, Rectangle и Ellipse. Все они наследуются от базового типа (класса или интерфейса) Shape. У Shape есть виртуальный метод вычисления площади GetSquare(), переопределенный по-своему в каждом наследнике.
Теперь представьте, что у вас есть List<Shape> - некая коллекция для неких целей (типа вам необходимо хранить сразу все разные Shape'ы в одном месте). Обчно коллекция используется для вычисления, скажем, общей площади (используется метод базового типа).
Но бывают случаи, когда вам при некоторых условиях нужно получить более конкретные данные: например, для всех прямоугольников, большей площади чем 10, вывести размеры. Как сделать такую задачу без приведения типов? Никак, в данной ситуации, потому что базовый тип Shape не хранит данных о размере прямоугольника. Придётся приводить элемент коллекции к более конкретному типу.
Пример для описанной задачи:
Код:
List<Shapes> shapes = ...;

//общая площадь(тут приводить не нужно, все данные есть в базовом типе):
float sumSquare = shapes.Sum(shape => shape.GetSquare());

//для всех прямоугольников, большей площади чем 10, вывести размеры (тут уже нужно):
foreach (Shape shape in shapes)
{
if (shape.GetSquare() > 10 && shape is Rectangle) {
Rectangle rect = (Rectangle)shape;
Console.WRiteLine(rect.Width + "; " + rect.Height)
}
}
Изобретатель велосипедов

Последний раз редактировалось Selestis; 07.02.2015 в 10:45.
Selestis вне форума Ответить с цитированием
Старый 07.02.2015, 10:43   #3
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Например, для полиморфизма.

Код:
abstract class Shape
{
    public abstract void Draw();
}

class Triangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Triangle");
    }
}

class Rectangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Rectangle");
    }
}
Код:
void DrawShape(Shape shape)
{
    shape.Draw();
}

    DrawShape(new Triangle());
    DrawShape(new Triangle());
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 07.02.2015, 11:41   #4
lomastr_
Форумчанин
 
Регистрация: 16.01.2015
Сообщений: 672
По умолчанию

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

при чем тут экземпляр базового и как он будет соотноситься с тем что действительно надо? а надо от DerivedClass...
lomastr_ вне форума Ответить с цитированием
Старый 07.02.2015, 12:15   #5
hoz
Форумчанин
 
Аватар для hoz
 
Регистрация: 29.06.2013
Сообщений: 132
По умолчанию

Цитата:
Сообщение от lomastr_ Посмотреть сообщение
ТС-у надо про ООП почитать
Я этим и занимаюсь. ООП слишком обширная тема. Конкретнее...

Цитата:
Сообщение от lomastr_ Посмотреть сообщение
при чем тут экземпляр базового и как он будет соотноситься с тем что действительно надо? а надо от DerivedClass...
Я ж доходчиво объяснил, что имею ввиду. Неужели не понятно? Я написал код простой, проверил. Если следовать подобному синтаксису без списков и абстракции, не видит данная переменная свойств и методов производного класса...

Например:
PHP код:
class Program
  
{
     static 
void Main(string[] args)
     {
       
BaseClass instance = new DerivedClass();
       
// ВОТ ЭТА ПЕРЕМЕННАЯ instance ничего не знает о метода Sum() производного класса DerivedClass. Это не понятно?
      
Console.WriteLine("instance is {0}"instance);

       
       
Console.ReadLine();
     }

     public class 
BaseClass
     
{
       private 
int countApple 5;

       public 
BaseClass()
       {
         
Console.WriteLine("BaseClass: On the table {0} apple..."countApple);
       }

     }

     public class 
DerivedClass BaseClass
     
{
      private 
int countBooks 8;
      private 
int a 1;
      private 
int b 3;

      public 
DerivedClass()
         : 
base()
      {
       
Console.WriteLine("DerivedClass: On the bed lays {0} books..."countBooks);
      }

      public 
int Sum()
      {
       return (
b);
      }
     }
  } 
Вот так не выйдет сделать:
PHP код:
static void Main(string[] args
     { 
       
BaseClass instance = new DerivedClass(); 
       
// ВОТ ЭТА ПЕРЕМЕННАЯ instance ничего не знает о метода Sum() производного класса DerivedClass. Это не понятно? 
      
Console.WriteLine("Sum is {0}"instance.Sum());  \\ ОШИБКА !!!! 

        
       
Console.ReadLine(); 
     } 
hoz вне форума Ответить с цитированием
Старый 07.02.2015, 12:19   #6
hoz
Форумчанин
 
Аватар для hoz
 
Регистрация: 29.06.2013
Сообщений: 132
По умолчанию

Selestis, с коллекциями я не знаю ещё. Сложный у Вас пример. Хотя кое-что я всё-таки понял. Благодарю за столь подробный ответ.


Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Например, для полиморфизма.

Код:
abstract class Shape
{
    public abstract void Draw();
}

class Triangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Triangle");
    }
}

class Rectangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Rectangle");
    }
}
Код:
void DrawShape(Shape shape)
{
    shape.Draw();
}

    DrawShape(new Triangle());
    DrawShape(new Triangle());
Alex11223, у Вас тут синтаксис для абстракции. А у меня там было синтаксис без абстракции:
PHP код:
BaseClass instance = new DirivedClass(); 
Это ж другой подход. Прыгать через эту ступеньку не хочу, не закрепив материал.
hoz вне форума Ответить с цитированием
Старый 07.02.2015, 12:45   #7
lomastr_
Форумчанин
 
Регистрация: 16.01.2015
Сообщений: 672
По умолчанию

Цитата:
Если следовать подобному синтаксису без списков и абстракции, не видит данная переменная свойств и методов производного класса...
да и пофик, нет и не надо, главное объект есть, интерфейса базового достаточно, задача решена, что тут не понятно?
Цитата:
Вот так не выйдет сделать:
если очень надо будет то сделают приведение (хотя это скорее о кривизне архитектуры говорит) о котором вы спрашивали в топике, но которого в топике не присутствовало.
lomastr_ вне форума Ответить с цитированием
Старый 07.02.2015, 13:51   #8
Selestis
Форумчанин
 
Аватар для Selestis
 
Регистрация: 21.01.2009
Сообщений: 719
По умолчанию

Если ваш пример ограничивать тем, что вы создаете объект-потомок и храните его в переменной с типом его предка, а затем хотите вызвать метод потомка, то конечно смысла в этом нет) Скорее всего этот пример привели в вашем источнике только для демонстрации, поэтому вам и не ясно его практическое применение.

Если вы ещё не дошли в изучении до полиморфизма, то лучше сначала просмотреть эту тему - потом сразу всё станет ясно. Суть в том, что метод предка может работать по-разному в разных потомках, так что вы можете и не знать кем именно является объект, используя его функциональность.
Изобретатель велосипедов
Selestis вне форума Ответить с цитированием
Старый 07.02.2015, 20:10   #9
hoz
Форумчанин
 
Аватар для hoz
 
Регистрация: 29.06.2013
Сообщений: 132
По умолчанию

Цитата:
Сообщение от lomastr_ Посмотреть сообщение
да и пофик, нет и не надо, главное объект есть, интерфейса базового достаточно, задача решена, что тут не понятно?
Откуда столько эмоций? Вопрос нормальный. Хотел увидеть или услышать внятный ответ. А Вы говорите так, как будто что-то невероятно сложное спрашиваю или слишком очевидное. Но сдаётся мне, что тема полиморфизма это самая сложная тема в ООП. По крайне мере мне на данный момент так видится.

Я написал вот код простой:

PHP код:
namespace Abstract
{
  class 
Program
  
{
    static 
void Main(string[] args)
    {
     
Base instance = new Repetuz();

     
Console.WriteLine("instance = {0} "instance);
     
      
Console.ReadLine();
    }

    abstract class 
Base
    
{
      public abstract 
void Draw();
    }

    class 
Repetuz Base
    
{
      public 
override void Draw()
      {
        
Console.WriteLine("Repetuz");
      }
    }
  }

В общем-то убедился очередной раз, что методы не вызвать никак в данном случае. Но зато это дало понять один момент.
По сути, как я понял, нам и не важно то, что методы потомков не вызываются из предка, так? Нам важно, чтоб потомок целиком выполнялся, и, именно, целиком! Так?
Т.е. если выполнять целиком его, то он нормально отрабатывается. А реализация скрывается от посторонних глаз? Например, в библиотеках...
Или ещё какие-то причины есть?
hoz вне форума Ответить с цитированием
Старый 07.02.2015, 21:03   #10
Selestis
Форумчанин
 
Аватар для Selestis
 
Регистрация: 21.01.2009
Сообщений: 719
По умолчанию

Цитата:
В общем-то убедился очередной раз, что методы не вызвать никак в данном случае.
Почему?
Код:
instance.Draw();
выведет "Repetuz" в консоль.
P.S. это и есть полиморфизм
Изобретатель велосипедов
Selestis вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Макрос для приведения к одному, одинаковому размеру графиков REztor Microsoft Office Excel 2 23.12.2012 22:28
Битва экстрасенсов. Приведения, души и т.д. TwiX Свободное общение 5 30.10.2011 15:22
Ошибка при присвоении объекту производного класса объекта базового класса с исп. явного приведения типов Lanx Помощь студентам 0 06.04.2011 20:24
Приведение к типу __Demon__ Общие вопросы C/C++ 1 27.09.2009 17:40
Проблема приведения типов Dec(Leprosus) Общие вопросы C/C++ 14 08.05.2008 04:24