Доступ к родительскому классу в ООП правильно

Я только начал программировать ООП и столкнулся с проблемой объема. В следующем проекте у меня есть мастер-класс под названием App. Класс App имеет классы Screens:Screen-класс и Navigation-класс как дочерние. Из класса навигации я хочу контролировать, какие экраны будут отображаться. Я не знаю, как это сделать...

Пожалуйста, проверьте код, чтобы полностью понять мои намерения

Ваша помощь очень ценится, я бы очень хотел научиться программированию, а не просто грязному решению:), но все предложения приветствуются!

// Main Class //
public class App extends Sprite
{
    private var screens:Array;
        private var screen1:Screen;
        private var screen2:Screen;
        private var screen3:Screen;
        private var screen4:Screen;

    public var currentScreen:String;
    //



    private var navigation:Navigation;

    public function App()
    {
        init();
    }

    private function init():void {
        buildScreens();

        buildNavigation();
    }

    private function buildScreens():void {
        screen1 = new Screen();
        screen1.name = 'startScreen';
        currentScreen = screen1.name;
        addChild(screen1);

        screen2 = new Screen();
        screen2.name = 'irrelevantA';

        screen3 = new Screen();
        screen3.name = 'irrelevantB';

        screen4 = new Screen();
        screen4.name = 'irrelevantC';


        screens = new Array(screen1, screen2, screen3, screen4);


    }

    private function buildNavigation():void {
        navigation = new Navigation(screens);
    }
}

// Screen Class //
public class Screen extends Sprite
{
    public function Screen()
    {
        // creates a new screen
    }
}


// Navigation Class //
public class Navigation extends Sprite
{
    private var buttons:Array;

    public function Navigation(screens:Array)
    {
        addButtons(screens);
    }

    private function addButtons(screens:Array):void {
        buttons = new Array();

        for each(var screen:Screen in screens) {
            var button:Button = new Button();
            button.link = screen.name;
            button.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
            buttons.push(button);
        }
    }

    private function mouseDown(e:MouseEvent):void {
        // THIS IS WHAT MY QUESTION IS ABOUT: How should I talk to the parent class in an OOP correct way?
        // and how can I add and remove a screen in the App class from here?

        // Here some of my tries
        // I don't think using parent to get there is a good way because next time it might be; parent.parent.parent
        trace(e.target.parent.parent.currentScreen);
        this.parent.currentScreen;
        stage.App.currentScreen;
        App.currentScreen;


        //---------------------------------
    }
}

// Button Class //
public class Button extends Sprite
{
    public var link:String;

    public function Button()
    {
        // creates a new button
    }
}

2 ответа

Решение

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

Вот пример. Сначала создайте пользовательское событие:

public class MyCustomEvent extends Event {

    public static const MENU_ITEM_SELECTED : String = "MENU_ITEM_SELECTED";
    public var selectedItem:String;
}

Затем пусть навигация отправит его при нажатии кнопки:

public class Navigation extends Sprite () {
    // ...
    private function onButtonClicked(ev:Event) : void {
        ev.stopPropagation();
        var custEvent:MyCustomEvent = new MyCustomEvent(MyCustomEvent.MENU_ITEM_SELECTED);
        custEvent.selectedItem = ev.target.name;
        this.dispatchEvent (custEvent);
    }
    // ...
}

Наконец, позвольте приложению обработать пользовательское событие и вызвать другой экран:

public class App {
    // ...
    public function createNavigation () : void {
        navigation = new Navigation ();
        navigation.addEventListener (MyCustomEvent.MENU_ITEM_SELECTED, onMenuItemSelected);
        // ... more stuff happening
    }
    // ...

    private function onMenuItemSelected (ev:MyCustomEvent) : void {
        switchToScreen (ev.selectedItem);
    }

    private function switchToScreen (name:String) : void {
        // choose screen by name, etc.
    }
}

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

По сути, вы хотите общаться вниз (от родителя к потомку), передавая ссылки в качестве аргументов (как вы делаете с массивом экранов) и вверх (от потомка к родителю), вызывая публичные функции.

Итак, в вашем случае что-то вроде этого:

Класс приложения:

private function buildNavigation():void {
   navigation = new Navigation(this, screens);
}
//etc
public function changeScreen(newScreen:int):void{
    //Your logic for adding/removing screens goes here
}

Класс навигации:

 private var app:App

 public function Navigation(app:App, screens:Array)
    {
        this.app = app
        addButtons(screens);
    }

    private function addButtons(screens:Array):void {
        buttons = new Array();

        for each(var screen:Screen in screens) {
            var button:Button = new Button();
            button.link = screen.name;
            button.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
            buttons.push(button);
        }
    }

    private function mouseDown(e:MouseEvent):void {
       app.changeScreens(2);
    }
}

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

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