С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.85/13: Рейтинг темы: голосов - 13, средняя оценка - 4.85
0 / 0 / 0
Регистрация: 21.11.2011
Сообщений: 22
1

Как сделать открытым свойство для наследника но закрытым для наследника наследника?

08.12.2014, 16:58. Показов 2572. Ответов 20
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть класс GameObject в котором есть свойство Coordinates
Класс Animal наследуется от GameObject и должен содержать метод MoveTo который изменяет Coordinates почутьчуть с учётом скорости животного
Класс Rabbit наследуется от Animal

Суть в том что Rabbit не должен иметь возможности изменять coordinates как ему вздумается. Он может изменять свои координаты только используя метод MoveTo доставшийся по наследству от Animal.
Если сделать свойство Coordinates private, то Animal не сможет с ним работать в методе MoveTo
Если сделать это свойство protected, то Rabbit сможет менять координаты как захочет.

Как реализовать такую схему, соблюдая принципы ооп?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.12.2014, 16:58
Ответы с готовыми решениями:

Как переопределить дружественную функцию ввода для класса наследника
Есть класс предок, который имеет такую вот дружественную функцию ввода: friend ifstream &...

Два конструктора для класса-наследника
Класс B является наследником класса A. Для класса B нужно определить 2 конструктора: один -...

Создание экземпляра для наследника абстрактного класса
Есть абстрактный базовый класс: class Base { public: int variable; virtual void...

Нельзя создать стиль для наследника кнопки
public enum ButtonState { Normal, MouseHover, Pressed } ...

20
2152 / 1289 / 516
Регистрация: 04.03.2014
Сообщений: 4,092
08.12.2014, 17:07 2
Цитата Сообщение от Tums37 Посмотреть сообщение
Если сделать это свойство protected, то Rabbit сможет менять координаты как захочет.
так и должно быть, если у разных животных будет разная реализация метода MoveTo
а если метод MoveTo в классе Animal не виртуальный, то и Coordinates в классе Animal делай приватным
0
0 / 0 / 0
Регистрация: 21.11.2011
Сообщений: 22
08.12.2014, 17:11  [ТС] 3
Цитата Сообщение от Metall_Version Посмотреть сообщение
так и должно быть, если у разных животных будет разная реализация метода MoveTo
а если метод MoveTo в классе Animal не виртуальный, то и Coordinates в классе Animal делай приватным
В том то и дело, что Coordinates находятся не в классе Animal, а в классе GameObject
0
814 / 422 / 169
Регистрация: 08.02.2013
Сообщений: 711
08.12.2014, 17:19 4
Tums37, если вы наследуете Кролика от GameObject, то скорее всего где-то есть примерно такой код:
C#
1
2
3
4
5
List<GameObject> objects; 
objects.Add(new Rabbit());
...
foreach(var obj in objects)
   obj.MoveTo(0); // тут будет ошибка
Не стоит запрещать программе выполнять методы. Можно запретить это делать в клиентском коде. Например обернув Кролика над GameObject:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class GameObject 
{
    public virtual void MoveTo()
    { Debug.WriteLine("GameObject.MoveTo"); }
}
 
class Rabbit
{
    GameObject obj = new GameObject();
 
    public void Move()
    {
        obj.MoveTo();
    }
        
    /* здесь нет MoveTo*/
 
    public static Rabbit Create(List<GameObject> AllObjects)
    {
        Rabbit r = new Rabbit();
        AllObjects.Add(r.obj);
        return r;
    }
}
Или вызывать исключение, если,по логике наследование от GameObject не нужно, но лишний код писать не хочется:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class GameObject 
{
    public virtual void MoveTo()
    { Debug.WriteLine("GameObject.MoveTo"); }
}
 
class Rabbit : GameObject
{
    public void Move()
    { 
        Debug.WriteLine("Rabbit.Move");
        base.MoveTo();
    }
 
    public override void MoveTo()
    {
        throw new Exception("Вызов MoveTo из класса Rabbit запрещен");
    }
}
0
0 / 0 / 1
Регистрация: 08.12.2014
Сообщений: 6
08.12.2014, 17:30 5
Как вариант: использовать в качестве базового родителя GameObject не класс, а интерфейс. Унаследовав его классом Animal объявляете его, как private и Rabbit доступ к нему не получит.
0
2152 / 1289 / 516
Регистрация: 04.03.2014
Сообщений: 4,092
08.12.2014, 17:35 6
Цитата Сообщение от Tums37 Посмотреть сообщение
В том то и дело, что Coordinates находятся не в классе Animal, а в классе GameObject
ну тогда делайте либо там метод движения, и закрывайте (privat) координаты, это если у всех движение будет одинаковое
либо в каждом классе реализуйте свой метод движения и координаты будут защищенными.
если у некоторых зверей будет одинаковый метод движения то используйте интерфейсы для каждого типа движения
0
0 / 0 / 0
Регистрация: 21.11.2011
Сообщений: 22
08.12.2014, 17:40  [ТС] 7
rRczZZ, Вы не так поняли мой вопрос.
Проблема не в вызове метода MoveTo, а в том, что я пытаюсь скрыть свойство Coordinates от Кролика.
Я хочу сделать так, чтобы человек, пишущий логику движений кролика не мог менять координаты как вздумается.
Чтобы он мог использовать только метод MoveTo класса Animal. А координаты должны храниться в классе GameObject, от которого наследуется Animal
0
2152 / 1289 / 516
Регистрация: 04.03.2014
Сообщений: 4,092
08.12.2014, 17:54 8
Цитата Сообщение от Tums37 Посмотреть сообщение
Я хочу сделать так, чтобы человек, пишущий логику движений кролика не мог менять координаты как вздумается.
как можно писать логику движения , при этом не изменив координаты ?
0
0 / 0 / 0
Регистрация: 21.11.2011
Сообщений: 22
08.12.2014, 18:00  [ТС] 9
Цитата Сообщение от Metall_Version Посмотреть сообщение
как можно писать логику движения , при этом не изменив координаты ?
Свойство Coordinates доступно для чтения, но изменять его напрямую нельзя
C#
1
2
3
4
5
private Point coordinates;
 
public Point Coordinates {
    get{return coordinates;}
}
0
2152 / 1289 / 516
Регистрация: 04.03.2014
Сообщений: 4,092
08.12.2014, 18:02 10
Цитата Сообщение от Tums37 Посмотреть сообщение
Свойство Coordinates доступно для чтения, но изменять его напрямую нельзя
вы не ответили на вопрос, что в вашем понимании тогда логика движения, если повлиять на месторасположение объекта мы не можем ?
0
3683 / 2594 / 719
Регистрация: 02.08.2011
Сообщений: 6,963
08.12.2014, 18:03 11
Цитата Сообщение от Metall_Version Посмотреть сообщение
если повлиять на месторасположение объекта мы не можем
Имелось ввиду изменить координаты объекта правильно, то есть только через метод MoveTo, не нарушая целостности.
1
0 / 0 / 0
Регистрация: 21.11.2011
Сообщений: 22
08.12.2014, 18:05  [ТС] 12
Цитата Сообщение от Metall_Version Посмотреть сообщение
вы не ответили на вопрос, что в вашем понимании тогда логика движения, если повлиять на месторасположение объекта мы не можем ?
Можем, используя метод MoveTo, в котором прописаны ограничения, чтобы кролик бежал с определённой скоростью, а не перемещался по полю как захочет.
0
3683 / 2594 / 719
Регистрация: 02.08.2011
Сообщений: 6,963
08.12.2014, 18:23 13
Вообще наследование - самое сильная связь между объектами, которая не разрывается даже во время выполнения.
((С) Тепляков). Так что если ваш класс наследуется (напрямую, либо где-то ниже в иерархии) от класса GameObject, то от этого уже не избавишься, потому что ниже модификатора protected только private, а с private в иерархии уже нету смысла. Но зато можно просто скрыть войство Coordinate от клиентского кода. Мб вы это хотели увидеть:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 public class SomeCoordinateObject
    {
       // your own structure 
    }
 
    public class GameObject
    {
        protected  SomeCoordinateObject Coordinate { get; set; }
    }
 
    public interface IGameAnimal
    {
        void MoveTo(SomeCoordinateObject coordinate);
    }
 
    public class GameRabbit : GameObject, IGameAnimal
    {
        public void MoveTo(SomeCoordinateObject coordinate)
        {
           throw new NotImplementedException();
        }
    }
Добавлено через 5 минут
Подкорректирую именование и иерархию:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class SomeCoordinateObject
    {
       // your own structure
    }
 
    public interface IMoveableGameObject
    {
        void MoveTo(SomeCoordinateObject coordinate);
    }
 
    public class GameObject: IMoveableGameObject
    {
        protected  SomeCoordinateObject Coordinate { get; set; }
        public void MoveTo(SomeCoordinateObject coordinate)
        {
            throw new NotImplementedException();
        }
    }
    
 
    public class GameRabbit : GameObject
    {
        public void MoveTo(SomeCoordinateObject coordinate)
        {
           throw new NotImplementedException();
        }
    }
 
    // где-то там:
     GameRabbit gr = new GameRabbit(); //доступен только MoveTo.
1
2152 / 1289 / 516
Регистрация: 04.03.2014
Сообщений: 4,092
08.12.2014, 18:23 14
Цитата Сообщение от Tums37 Посмотреть сообщение
Можем, используя метод MoveTo, в котором прописаны ограничения, чтобы кролик бежал с определённой скоростью, а не перемещался по полю как захочет.
никак, если Animal видит свойство родителя - координаты , то и все его наследники будут видеть. Это суть ООП

а чем вам это не нравится?
0
3683 / 2594 / 719
Регистрация: 02.08.2011
Сообщений: 6,963
08.12.2014, 18:36 15
В методе MoveTo не обязательно просто присваивать новое значение для Coordinate - уже можно проводить валидацию.

Добавлено через 6 минут
Там еще наверно понадобится направление и приращение. Смотрите как у структуры Point передвижение устроено (есть перегрузка с dx и dy).
1
0 / 0 / 0
Регистрация: 21.11.2011
Сообщений: 22
08.12.2014, 18:40  [ТС] 16
Цитата Сообщение от IamRain Посмотреть сообщение
// где-то там:
* * *GameRabbit gr = new GameRabbit(); //доступен только MoveTo.
Моя задача - скрыть свойство Coordinates от самого класса Rabbit. Предполагается, что класс Rabbit или Wolf или ещё какой нибудь будет писать человек, который сильно хочет всё испортить.
Нельзя позволять изменять свойство Coordinates в классе Rabbit.

Конечно можно просто перенести метод MoveTo в класс Gameobject, но это не очень хорошо, так как помимо животных на поле могут быть камни например или трава, которые не могут куда либо перемещаться и у которых не должно быть ни скорости ни метода MoveTo
0
3683 / 2594 / 719
Регистрация: 02.08.2011
Сообщений: 6,963
08.12.2014, 18:58 17
Цитата Сообщение от Tums37 Посмотреть сообщение
Моя задача - скрыть свойство Coordinates от самого класса Rabbit
Думаю, такое нельзя сделать.

Добавлено через 10 минут
Вообще в этом суть наследования - моделировать отношение "'является", то есть перенимать свойства родительского объекта и добавлять собственные. Если не хотите перенимать свойства родительского объекта - тогда не наследуйтесь от него.
1
286 / 192 / 56
Регистрация: 25.12.2012
Сообщений: 640
08.12.2014, 19:33 18
Цитата Сообщение от IamRain Посмотреть сообщение
Думаю, такое нельзя сделать.
Можно. Пихайте в отдельную DLL.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace DLL
{
    public class GameObject 
    {
        internal int Coordinates
        {
            get
            {
                return 0;
            }
        }
    }
    public class Animal : GameObject
    {
        public int MoveTo()
        {
            return Coordinates;
        }
    }
 
}
1
3683 / 2594 / 719
Регистрация: 02.08.2011
Сообщений: 6,963
08.12.2014, 19:41 19
Но в случае с одним свойством объект не имеет никакого смысла - он пустой.

Добавлено через 1 минуту
Тогда уж internal как модификатор класса.
0
2152 / 1289 / 516
Регистрация: 04.03.2014
Сообщений: 4,092
08.12.2014, 19:48 20
Цитата Сообщение от IamRain Посмотреть сообщение
Но в случае с одним свойством объект не имеет никакого смысла - он пустой.
при чем тут это, человек просто показал как сделать то, что хочет ТС, без деталей реализации.

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

тем более метод MoveTo должен виртуальным, и переопределенным для разных зверей , ибо кролик и птица могут двигаться совершенно по разному.. (птица может двигаться еще и вверх) соответственно логика метода движения должна быть написана в каждом классе , или добавить еще пару абстракных классов по методам передвижения зверей, или же интерфейсов
1
08.12.2014, 19:48
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.12.2014, 19:48
Помогаю со студенческими работами здесь

Как написать класс MainFile, от которого нельзя сделать наследника
PHP Написать класс MainFile, от которого нельзя сделать наследника. Класс состоит из 3...

Создать абстрактный класс фигур и сделать 2 наследника (треугольник, прямоугольник)
Доброго времени суток. Задание такое : создать абстрактный класс фигур и сделать 2 наследника(...

Как объявить наследника TThread?
Вот что есть: class TPLAThread : public TThread { private: AnsiString strField; Variant...

Как сделать явное приведения переменной типа класса-наследника к типу базового класса?
Читал, что для этого нужно явное приведение к типу, но на практике выдаёт ошибку. Вот код: using...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru