C#   Уроки программирования с нуля. Си-шарп для чайников   C#

Здравствуйте, гость!
Вход
Регистрация


Массив указателей на базовый класс в Си-шарп. Операторы is и as
Данный урок является продолжением предыдущего, посвященного наследованию.

В Си-шарп есть возможность создания массива (или списка) указателей на базовый класс в котором в качестве элементов могут быть объекты класса-наследника. Например, мы можем создать массив объектов Животное, и элементами такого массива будут объекты классов Собака, Кошка. Пример:

class Animal
{
   public string Name { get; set; }

   public Animal(string name)
   {
     Name = name;
   }
}
class Dog : Animal
{
   public Dog(string name) : base(name)
   { }

   public void Guard()
   {
     // собака охраняет
   }
}
class Cat : Animal
{
  public Cat(string name) : base(name)
   { }

  public void CatchMouse()
  {
     // кошка ловит мышь
  }
}

class Program
{
   static void Main(string[] args)
   {
     List<Animal> animals = new List<Animal>(); // создаем список указателей на базовый класс
     animals.Add(new Dog("Барбос"));
     animals.Add(new Cat("Барсик"));
     animals.Add(new Dog("Полкан"));

     foreach (Animal animal in animals)
     {
       Console.WriteLine(animal.Name);
     }
     Console.ReadLine();
  }
}


Хотя как элементы в этот список мы добавляли объекты классов-наследников Собака и Кошка, будучи элементами списка указателей на базовый класс, эти объекты преобразовываются к объектам базового класса, и мы имеем доступ только к той части объектов, которая описана в базовом классе – мы не можем здесь вызвать методы Guard() или CatchMouse(), но при этом имеем доступ к имени животного.

Обратное здесь невозможно. Нельзя создать массив объектов класса Собака, и записать в него объекты класса Животное.

Оператор is

Оператор is работает очень просто – он проверяет совместимость объекта с указанным типом (принадлежит ли объект определенному классу). Оператор is возвращает истину (true), если объект принадлежит классу. Истинна будет также при проверке совместимости объекта класса-наследника и базового класса:

static void Main(string[] args)
{
   Dog dog1 = new Dog("Барбос");

   Console.WriteLine(dog1 is Dog); // true
   Console.WriteLine(dog1 is Animal); // true
   Console.WriteLine(dog1 is Cat); // false
   Console.ReadLine();
}


Пользуясь оператором is и явным преобразованием, теперь мы можем полноценно использовать массив указателей на базовый класс:

class Animal
{
   public string Name { get; set; }

   public Animal(string name)
   {
     Name = name;
   }
}
class Dog : Animal
{
   public Dog(string name) : base(name)
   { }

   public void Guard()
  {
     Console.WriteLine(Name + " охраняет");
   }
}
class Cat : Animal
{
  public Cat(string name) : base(name)
   { }

   public void CatchMouse()
   {
     Console.WriteLine(Name + " ловит мышь");
   }
}

class Program
{
   static void Main(string[] args)
  {
     List<Animal> animals = new List<Animal>();
     animals.Add(new Dog("Барбос"));
     animals.Add(new Cat("Барсик"));
     animals.Add(new Dog("Полкан"));

     foreach (Animal animal in animals)
     {
       if (animal is Dog) // проверяем является ли данное животное собакой
         ((Dog)animal).Guard();
       else ((Cat)animal).CatchMouse();
     }
     Console.ReadLine();
   }
}

Здесь, использовав явное преобразование, мы получаем полный доступ к объектам из списка, и можем вызывать методы Guard() и CatchMouse().

Оператор as

В примере выше, вместо явного приведения типов можно было использовать оператор as. (Dog)animal эквивалентно выражению animal as Dog. Разница между оператором as и явным приведением лишь в том, что в случае невозможности преобразования, оператор as возвращает null, тогда как явное приведение выбрасывает исключение. Пример программы выше, только уже с оператором as:

class Program
{
   static void Main(string[] args)
   {
   List<Animal> animals = new List<Animal>();
   animals.Add(new Dog("Барбос"));
   animals.Add(new Cat("Барсик"));
   animals.Add(new Dog("Полкан"));

   foreach (Animal animal in animals)
   {
       if (animal is Dog) // проверяем является ли данное животное собакой
         (animal as Dog).Guard();
       else (animal as Cat).CatchMouse();
   }
   Console.ReadLine();
   }
}

Понравилась статья? Подпишись на рассылку и узнавай первым о новых уроках по почте!


Поделиться с друзьями:
01 авг 2013 16:21
DedoK 16 фев 2017 15:17
спасибо за сайт, пример с волшебниками и лучниками на этом сайте смог объянить мне зачем нужно ООП. До этого я делал несколько раз попытки понять ООП читая статьи на других сайтах, но они были безуспешны.

Если в краце то фишка ООП в том что бы избавиться от бесконечных "IF"-ов.


К сожалению пример с Собаками и Кошкой не столь удачный. Если мы добавим Жирафа то заставим его ловить мышь. Сама архитектура не правильная. У класса животных должен быть метод Служить(), базовый пустой. Тогда ни каких is, as не понадобилось бы. Жираф просто откосил бы.

Но всё равно, ещё раз спасибо.

Князь 25 июл 2016 23:58
Написать программу, которая позволяет создавать список заемщиков и лиц, разместивших депозит, банка, с указанием суммы кредита/депозита. Добавить заемщика и депозитора, вывести на экран список заемщиков и депозиторов.



namespace Список_заемщиков
{
class Bank
{
public string Name_debtor;
public string Name_deposit;
public int Sum_Credit;

public Bank (string name)
{
}
}

class Debtor : Bank
{
public Debtor(string name): base(name)
{
Name_debtor = name;
}
}

class Deposit : Bank
{
public Deposit(string name,int sum_credit) : base(name)
{
Name_deposit = name;
Sum_Credit = sum_credit;
}
}

class Program
{
static void Main(string[] args)
{
List<Bank> bank = new List<Bank>();
bank.Add(new Deposit("Барсук И.Ю.", 56000));
bank.Add(new Deposit("Ривс А.Е.", 105000));
List<Bank> bank2 = new List<Bank>();
bank2.Add(new Debtor("Иванов П.С."));
bank2.Add(new Debtor("Мышкин А.А."));
Console.WriteLine("Список депозиторов с указанием суммы:");
foreach (Bank banks in bank)
{

Console.WriteLine(banks.Name_deposit);
Console.WriteLine(banks.Sum_Credit);
}
Console.WriteLine("\n");
Console.WriteLine("Список заемщиков:");
foreach (Bank banks in bank2)
{
Console.WriteLine(banks.Name_debtor);
}

Console.ReadLine();
}
}
}

dmitry_zon 18 фев 2016 14:39
Всем peace!
Написать программу, которая позволяет создавать список заемщиков и лиц, разместивших депозит, банка, с указанием суммы кредита/депозита. Добавить заемщика и депозитора, вывести на экран список заемщиков и депозиторов.


namespace Lesson18
{
class Customer
{
public string CustomerFirstName;
public string CustomerLastName;
public int Amount;
public Customer(string FirstName, string LastName, int amount)
{
CustomerFirstName=FirstName;
CustomerLastName=LastName;
Amount=amount;
}
}
class Loaner:Customer
{
public Loaner(string FirstName, string LastName, int amount):base(FirstName, LastName, amount)
{ }
public void LoanerInfo()
{
Console.WriteLine("Loaner " +CustomerFirstName+" "+CustomerLastName+" has LOAN amount "+Amount);
}
}
class Depositor:Customer
{
public Depositor(string FirstName, string LastName, int amount):base(FirstName, LastName, amount)
{ }
public void DepositorInfo()
{
Console.WriteLine("Depositor " + CustomerFirstName+" "+CustomerLastName+" has a DEPOSIT amount "+Amount);
}
}
class Program
{
static void Main(string[] args)
{
List<Customer> customer = new List<Customer>();
customer.Add(new Depositor("Vladimir", "Petrov", 10000));
customer.Add(new Loaner("Ivan", "Vladimirov", 15000));
foreach (Customer record in customer)
{
if (record is Depositor)
(record as Depositor).DepositorInfo();
else
(record as Loaner).LoanerInfo();
}
Console.ReadKey();
}
}
}


Игорь 28 янв 2016 08:09
class Engineer
{
public string name;
int categori;
public Engineer(string name, int categori)
{
this.name = name;
this.categori = categori;
}

}
class technologi : Engineer
{
public technologi(string name, int categori)
: base(name, categori)
{
}
}
class construktori : Engineer
{
public construktori(string name, int categori)
: base(name, categori)
{
}
}

class Program
{
static void Main(string[] args)
{
List<Engineer> imena = new List<Engineer>();
imena.Add(new Engineer("Попов", 32));
imena.Add(new technologi("Пирогов", 44));
imena.Add(new construktori("Романова", 64));
imena.Add(new technologi("Шандрин", 48));

foreach (Engineer set in imena)
{
try
{
if (set is technologi)
{
Console.WriteLine(set.name);
}
else
{
Console.WriteLine(" ");
}
}
catch (Exception)
{
Console.WriteLine("Ошибочка");

}

vv-ch 07 дек 2015 17:46
Решил запариться и применить то, что умею


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace ConsoleApplication1
{
class Figure
{
protected string Name { get; set; }
protected double Center_x { get; set; }
protected double Center_y { get; set; }
public Figure()
{
Name = "Noname";
Center_x = 0;
Center_y = 0;
}
public Figure(double x, double y, string name)
{
Center_x = x;
Center_y = y;
Name = name;
}
}
class Triangle : Figure
{
private double A { get; set; }
private double B { get; set; }
private double C { get; set; }
private double Square { get; set; }
public double GetSquare(double a, double b, double c) {
double p = (a + b + c) / 2.0;
double sq = Math.Sqrt(p*(p-a)*(p-b)*(p-c));
return sq;
}
public Triangle() : base ()
{
A = 0;
B = 0;
C = 0;
Square = 0;
}
public Triangle(double a, double b, double c, double x, double y, string name) : base(x, y, name)
{
A = a;
B = b;
C = c;
Square = GetSquare(A, B, C);
}
public void Output(StreamWriter writer) {
writer.WriteLine("==========================");
writer.WriteLine();
writer.WriteLine();
writer.WriteLine("Данные Треугольника << " + Name + " >>:");
writer.WriteLine("Длины сторон:");
writer.WriteLine("\tA = " + A);
writer.WriteLine("\tB = " + B);
writer.WriteLine("\tC = " + C);
writer.WriteLine("Площадь:");
writer.WriteLine("\tS = " + Square);
writer.WriteLine();
writer.WriteLine();
writer.WriteLine("==========================");
}
}
class Round : Figure
{
private double R { get; set; }
private double Square { get; set; }
private double Circumference { get; set; }
public double GetSquare(double r)
{
return Math.PI * r * r;
}
public double GetCircumference(double r)
{
return Math.PI * r * 2;
}
public Round() : base ()
{
R = 0;
Square = 0;
Circumference = 0;
}
public Round(double r, double x, double y, string name) : base(x, y, name)
{
R = r;
Square = GetSquare(r);
Circumference = GetCircumference(r);
}
public void Output(StreamWriter writer)
{
writer.WriteLine("==========================");
writer.WriteLine();
writer.WriteLine();
writer.WriteLine("Данные круга << " + Name + " >>:");
writer.WriteLine("Радиус:");
writer.WriteLine("\tR = " + R);
writer.WriteLine("Площадь:");
writer.WriteLine("\tS = " + Square);
writer.WriteLine("Длина окружности:");
writer.WriteLine("\tL = " + Circumference);
writer.WriteLine();
writer.WriteLine();
writer.WriteLine("==========================");
}

}
class Input
{
public static void Message(int n)
{
string[] s = {
/*0*/ "",
/*1*/ "\tВы ввели некорректные данные, попробуйте еще раз: ",
/*2*/ "Введите колличество фигур: ",
/*3*/ "\tВведите абциссу центра фигуры: ",
/*4*/ "\tВведите ординату центра фигуры: ",
/*5*/ "\tВведите радиус круга: ",
/*6*/ "\tВведите длину стороны А трегуольника: ",
/*7*/ "\tВведите длину стороны B трегуольника: ",
/*8*/ "\tВведите длину стороны C трегуольника: ",
/*9*/ "",
/*10*/ "\tЭто треугольник или круг? (тр/кр): ",
/*11*/ "\tВведите имя фигуры: "
};
Console.Write(s[n]);
}
public static int Int_(int flag)
{
Message(flag);
try
{
int n = Convert.ToInt32(Console.ReadLine());
Message(9);
return n;
}
catch (Exception)
{
Message(1);
return Int_(0);
}
}
public static double Double_(int flag)
{
Message(flag);
try
{
double n = Convert.ToDouble(Console.ReadLine());
Message(9);
return n;
}
catch (Exception)
{
Message(1);
return Double_(0);
}
}
public static string String_(int flag)
{
Message(flag);
try
{
string n = Console.ReadLine();
Message(9);
return n;
}
catch (Exception)
{
Message(1);
return String_(0);
}
}
public static bool TrKr(int flag)

{
Message(flag);
string s = Console.ReadLine();
switch(s)
{
case "тр":
return false;
case "кр":
return true;
default:
Message(1);
return TrKr(0);
}
}
}
class Program
{
static Triangle Tr_inp()
{
double x = Input.Double_(3);
double y = Input.Double_(4);
string name = Input.String_(11);
double a = Input.Double_(6);
double b = Input.Double_(7);
double c = Math.Min(Input.Double_(8), a+b);
return new Triangle(a, b, c, x, y, name);
}
static Round Rnd_inp()
{
double x = Input.Double_(3);
double y = Input.Double_(4);
string name = Input.String_(11);
double r = Input.Double_(5);
return new Round(r, x, y, name);
}
static void Main(string[] args)
{
int n = Math.Abs(Input.Int_(2));
List < Figure > geom = new List < Figure >();
for (int i = 1; i <= n; i++) {
Console.WriteLine("\n\n" + (new string('-', 50)) + "\n\n");
Console.WriteLine("Введите данные фигуры №" + i + ":");
bool fig = Input.TrKr(10);
if (!fig)
{
Triangle f = Tr_inp();
geom.Add(f);
}
else
{
Round f = Rnd_inp();
geom.Add(f);
}
Console.WriteLine("\n\n" + (new string('-', 50)) + "\n\n");
}
Directory.CreateDirectory("C:\\Users\\SP\\Desktop\\Дирректория про фигуры");
StreamWriter writer = new StreamWriter("C:\\Users\\SP\\Desktop\\Дирректория про фигуры\\нормальный такой файл.txt");
foreach (Figure i in geom)
{
if (i is Triangle) (i as Triangle).Output(writer);
else (i as Round).Output(writer);
}
writer.Close();
}
}
}

Anatoliy 02 ноя 2015 01:29
как удалить обект списка с названием барбосик? через Remove чтото не получается

List<Animal> animals = new List<Animal>(); // создаем список указателей на базовый класс
animals.Add(new Dog("Барбос"));
animals.Add(new Cat("Барсик"));
animals.Add(new Dog("Полкан"));

Максим 13 авг 2015 12:35
Anatoliy
---
Без скобок объект не будет восприниматься компилятором преобразованным, такой синтаксис

Anatoliy 12 авг 2015 22:56
Почему здесь указатели, при преобразировании брались в скобки еще раз?

((Dog)animal).Guard();
else ((Cat)animal).CatchMouse();

Сергей 31 июл 2015 20:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication5
{
class Animal
{
public string name { get; set; }
private double weight;
public Animal(string name,double weight)
{
this.name=name;
this.weight=weight;
}

public double Weight
{
get
{return weight;}

set
{
if(value<1)
weight=1;
else if (value>20)
weight=20;
else weight=value;
}
}

}
class Dog:Animal
{
public string color { get; set; }
public Dog(string name,double weight,string color):base(name,weight)
{
this.color = color;
}
public void showweight()
{

Console.WriteLine(Weight+" :Weight");
}
}
class Cat:Animal
{
private double lenghtoftail { get; set; }
public Cat(string name,double weight,double lengthoftail):base(name,weight)
{
this.lenghtoftail = lenghtoftail;
}
public void showWeight()
{

Console.WriteLine(Weight+":Weight");

}
}
class Program
{
static void Main(string[] args)
{
List<Animal> animals = new List<Animal>();
animals.Add(new Dog("Barbos", 25, "red"));
animals.Add(new Cat("Barsik", 8, 5));

foreach (Animal animal in animals)
{
if (animal is Dog)
((Dog)animal).showweight();
else (animal as Cat).showWeight();
}
Console.ReadLine();
}
}
}
Как-то так

Maro 14 июл 2015 19:42
очень нравятся уроки! СПАСИБО Автору!

Maro 14 июл 2015 19:41
мне кажется стоило бы указать, что для работы с List нужно подключить System.Collections.Generic?..

sergey 06 июл 2015 11:16
В данном уроке было бы актуально сказать что фишка с масивом работает только если в конструкторах один аргумент как в примере ((name)) если несколько то не работает. Если у кого работает то пример в студию.

Максим 02 июл 2015 20:42
Лия
---
Нету пока

Лия 02 июл 2015 11:58
А домашнее ???

Flamingo 07 июн 2015 20:28
Ребята, старайтесь помимо заданий на сайте придумывать себе свои.
Благодаря этому лучше материал запомнится, и даже если Д/З отсутствует
Будет возможность освоить какую-либо статью.

Максим 10 мар 2015 11:55
AlPer
---
Возможность есть, но пока на очереди урок про http

AlPer 10 мар 2015 11:17
Класс List C#, List<> C#

может быть сделать отдельно урок на тему данного класса? есть такая возможность?

AlPer 26 фев 2015 21:11
Домашнее задание хочу. Уж больно сложный урок. Надо бы закрепить...=)))

Lucifer 25 сен 2013 15:25
Admin
_______

Уже знаю и на мой взгляд он не актуален.

Максим 20 сен 2013 16:36
Lucifer
---
Почему вы так говорите о windows forms? Уже знаете как с этим работать, или не видите смысла это изучать? Web штука непростая и переход сразу будет сложен

Lucifer 19 сен 2013 12:26
а может ну его этот windows forms ? Не будет ли лучше перейти сразу к web или WPF ?

Максим 23 авг 2013 23:14
John
---
на днях будут

John 23 авг 2013 08:41
Не хочу показаться грубым, но когда, блин, будут новые уроки?

Максим 15 авг 2013 15:59
Сергей
---
По консоли есть еще что учить. Дальше, думаю, будет Windows Forms. До Web еще далековато

Сергей 15 авг 2013 13:30
Будет ли продолжение и переход от консоли к web ? =)
Меня лично интересует соединение с БД.


Добавить комментарий:

Имя (обязат.)
E-mail (обязат., не публикуется)


Для вставки ваших программ пользуйтесь кнопкой "исходный код"
Вёрстка сайта с нуля

Уникальный Видеокурс!

"Научись верстать сайты и заработай на этом!"

Получить видеокурс

Подпишись на курс по программированию, и узнавай первым о новых уроках!

RSS подписка Страничка Вконтакте Мы в Twitter
Бесплатный курс по основам PHP
Ошибка в тексте? Выделите ее мышкой и нажмите Ctrl+Enter
Поблагодарить автора: Номер карты (ПриватБанк)
5168 7572 4170 8660
WebMoney
R372544961915 U685637142028 Z999792764387
Наверх
Система Orphus